summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java258
-rw-r--r--api/current.txt7
-rwxr-xr-xapi/system-current.txt128
-rw-r--r--core/java/android/app/Activity.java34
-rw-r--r--core/java/android/app/ActivityManager.java26
-rw-r--r--core/java/android/app/ApplicationPackageManager.java58
-rw-r--r--core/java/android/app/IActivityManager.aidl10
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java43
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl1
-rw-r--r--core/java/android/app/usage/UsageEvents.java38
-rw-r--r--core/java/android/content/Intent.java29
-rw-r--r--core/java/android/content/LocusId.aidl19
-rw-r--r--core/java/android/content/integrity/AppInstallMetadata.java22
-rw-r--r--core/java/android/content/integrity/AtomicFormula.java322
-rw-r--r--core/java/android/content/integrity/CompoundFormula.java56
-rw-r--r--core/java/android/content/integrity/Formula.java103
-rw-r--r--core/java/android/content/integrity/IntegrityFormula.java277
-rw-r--r--core/java/android/content/integrity/IntegrityUtils.java (renamed from services/core/java/com/android/server/integrity/IntegrityUtils.java)8
-rw-r--r--core/java/android/content/integrity/Rule.java13
-rw-r--r--core/java/android/content/om/OverlayManager.java48
-rw-r--r--core/java/android/content/pm/PackageManager.java49
-rw-r--r--core/java/android/content/pm/SuspendDialogInfo.java102
-rw-r--r--core/java/android/hardware/Sensor.java19
-rw-r--r--core/java/android/hardware/SensorEvent.java10
-rw-r--r--core/java/android/net/ConnectivityDiagnosticsManager.java48
-rw-r--r--core/java/android/net/IConnectivityDiagnosticsCallback.aidl28
-rw-r--r--core/java/android/net/IConnectivityManager.aidl5
-rw-r--r--core/java/android/net/NetworkCapabilities.java49
-rw-r--r--core/java/android/os/BatteryStatsManager.java2
-rw-r--r--core/java/android/os/TelephonyServiceManager.java8
-rw-r--r--core/java/android/permission/PermissionManager.java24
-rw-r--r--core/java/android/provider/Settings.java9
-rw-r--r--core/java/android/service/notification/StatusBarNotification.java20
-rw-r--r--core/java/android/view/IWindowManager.aidl5
-rw-r--r--core/java/android/view/SurfaceControl.java1
-rw-r--r--core/java/android/view/SurfaceView.java9
-rw-r--r--core/java/android/view/SyncRtSurfaceTransactionApplier.java8
-rw-r--r--core/java/android/view/ViewRootImpl.java12
-rw-r--r--core/java/com/android/internal/app/BlockedAppActivity.java86
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java3
-rw-r--r--core/java/com/android/internal/app/SuspendedAppActivity.java119
-rw-r--r--core/proto/android/server/usagestatsservice_v2.proto2
-rw-r--r--core/res/AndroidManifest.xml7
-rw-r--r--core/res/res/values/strings.xml12
-rw-r--r--core/res/res/values/symbols.xml5
-rw-r--r--core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java323
-rw-r--r--core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java149
-rw-r--r--core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java214
-rw-r--r--core/tests/coretests/src/android/content/integrity/IntegrityUtilsTest.java (renamed from services/tests/servicestests/src/com/android/server/integrity/IntegrityUtilsTest.java)32
-rw-r--r--core/tests/coretests/src/android/content/integrity/RuleTest.java12
-rw-r--r--location/java/android/location/LocationManager.java2
-rw-r--r--location/java/android/location/LocationManagerInternal.java44
-rw-r--r--location/java/com/android/internal/location/ILocationProvider.aidl2
-rw-r--r--location/java/com/android/internal/location/ILocationProviderManager.aidl2
-rw-r--r--location/lib/api/current.txt7
-rw-r--r--location/lib/java/com/android/location/provider/LocationProviderBase.java75
-rw-r--r--media/java/android/media/MediaCodecInfo.java8
-rw-r--r--media/java/android/media/MediaFormat.java12
-rw-r--r--media/java/android/media/MediaMetadataRetriever.java272
-rw-r--r--media/jni/android_media_MediaCodec.cpp140
-rw-r--r--media/jni/android_media_MediaMetadataRetriever.cpp2
-rw-r--r--packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java2
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java2
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java3
-rw-r--r--packages/SystemUI/res/values/config.xml1
-rw-r--r--packages/SystemUI/res/values/dimens.xml3
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/DumpController.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java393
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java2
-rw-r--r--proto/src/task_snapshot.proto1
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java5
-rw-r--r--services/core/java/android/app/usage/UsageStatsManagerInternal.java18
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java14
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java47
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java122
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java16
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java2
-rw-r--r--services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java29
-rw-r--r--services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java15
-rw-r--r--services/core/java/com/android/server/integrity/engine/RuleEvaluator.java8
-rw-r--r--services/core/java/com/android/server/integrity/model/BitOutputStream.java2
-rw-r--r--services/core/java/com/android/server/integrity/parser/BinaryFileOperations.java3
-rw-r--r--services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java17
-rw-r--r--services/core/java/com/android/server/integrity/parser/RuleXmlParser.java14
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java21
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java14
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java13
-rw-r--r--services/core/java/com/android/server/location/AbstractLocationProvider.java47
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java2
-rw-r--r--services/core/java/com/android/server/location/LocationProviderProxy.java12
-rw-r--r--services/core/java/com/android/server/location/MockProvider.java17
-rw-r--r--services/core/java/com/android/server/location/MockableLocationProvider.java6
-rw-r--r--services/core/java/com/android/server/location/PassiveProvider.java2
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java30
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecord.java16
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecordLogger.java142
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java69
-rw-r--r--services/core/java/com/android/server/om/OverlayActorEnforcer.java5
-rw-r--r--services/core/java/com/android/server/pm/AppsFilter.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java17
-rw-r--r--services/core/java/com/android/server/stats/pull/StatsPullAtomService.java66
-rw-r--r--services/core/java/com/android/server/webkit/WebViewUpdateService.java32
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java25
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartInterceptor.java39
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java19
-rw-r--r--services/core/java/com/android/server/wm/ConfigurationContainer.java61
-rw-r--r--services/core/java/com/android/server/wm/LockTaskController.java16
-rw-r--r--services/core/java/com/android/server/wm/Task.java4
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java4
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotLoader.java4
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotPersister.java1
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java53
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java9
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java16
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java22
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java16
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java113
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java41
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/parser/BinaryFileOperationsTest.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java241
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java31
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java20
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java18
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/utils/TestUtils.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java25
-rw-r--r--services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java18
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java3
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java65
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java53
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java17
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java23
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java35
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java17
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java4
-rw-r--r--services/usage/java/com/android/server/usage/IntervalStats.java17
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsProtoV2.java9
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java15
-rw-r--r--telephony/common/com/android/internal/telephony/CarrierAppUtils.java203
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java24
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl5
-rw-r--r--tests/net/common/java/android/net/NetworkCapabilitiesTest.java1
-rw-r--r--tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java52
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java18
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java3
152 files changed, 4228 insertions, 1880 deletions
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index 4c8790f47bb6..1e92826ee8a0 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -15,161 +15,51 @@
*/
package com.android.server.stats;
-import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED;
-import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
-import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
-import static android.os.Process.getUidForPid;
-import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
-import static android.os.storage.VolumeInfo.TYPE_PUBLIC;
-
-import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
-import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
-import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
-import static com.android.server.stats.pull.ProcfsMemoryUtil.forEachPid;
-import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs;
-import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.ActivityManagerInternal;
+
import android.app.AlarmManager;
import android.app.AlarmManager.OnAlarmListener;
-import android.app.AppOpsManager;
-import android.app.AppOpsManager.HistoricalOps;
-import android.app.AppOpsManager.HistoricalOpsRequest;
-import android.app.AppOpsManager.HistoricalPackageOps;
-import android.app.AppOpsManager.HistoricalUidOps;
-import android.app.INotificationManager;
-import android.app.ProcessMemoryState;
import android.app.StatsManager;
-import android.bluetooth.BluetoothActivityEnergyInfo;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.UidTraffic;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PermissionInfo;
-import android.content.pm.UserInfo;
-import android.hardware.biometrics.BiometricsProtoEnums;
-import android.hardware.face.FaceManager;
-import android.hardware.fingerprint.FingerprintManager;
-import android.net.ConnectivityManager;
-import android.net.INetworkStatsService;
-import android.net.Network;
-import android.net.NetworkRequest;
-import android.net.NetworkStats;
-import android.net.wifi.WifiManager;
-import android.os.BatteryStats;
-import android.os.BatteryStatsInternal;
import android.os.Binder;
-import android.os.Build;
import android.os.Bundle;
-import android.os.CoolingDevice;
-import android.os.Environment;
-import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IStatsCompanionService;
import android.os.IStatsd;
-import android.os.IStoraged;
-import android.os.IThermalEventListener;
-import android.os.IThermalService;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
-import android.os.Parcelable;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.StatsFrameworkInitializer;
-import android.os.StatFs;
-import android.os.StatsLogEventWrapper;
-import android.os.SynchronousResultReceiver;
import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.Temperature;
import android.os.UserHandle;
import android.os.UserManager;
-import android.os.connectivity.WifiActivityEnergyInfo;
-import android.os.storage.DiskInfo;
-import android.os.storage.StorageManager;
-import android.os.storage.VolumeInfo;
-import android.provider.Settings;
-import android.stats.storage.StorageEnums;
-import android.telephony.ModemActivityInfo;
-import android.telephony.TelephonyManager;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
import android.util.Slog;
-import android.util.StatsLog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.app.procstats.IProcessStats;
-import com.android.internal.app.procstats.ProcessStats;
-import com.android.internal.os.BatterySipper;
-import com.android.internal.os.BatteryStatsHelper;
-import com.android.internal.os.BinderCallsStats.ExportedCallStat;
-import com.android.internal.os.KernelCpuSpeedReader;
-import com.android.internal.os.KernelCpuThreadReader;
-import com.android.internal.os.KernelCpuThreadReaderDiff;
-import com.android.internal.os.KernelCpuThreadReaderSettingsObserver;
-import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
-import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
-import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
-import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
-import com.android.internal.os.KernelWakelockReader;
-import com.android.internal.os.KernelWakelockStats;
import com.android.internal.os.LooperStats;
-import com.android.internal.os.PowerProfile;
-import com.android.internal.os.ProcessCpuTracker;
-import com.android.internal.os.StoragedUidIoStatsReader;
import com.android.internal.util.DumpUtils;
import com.android.server.BinderCallsStatsService;
import com.android.server.LocalServices;
-import com.android.server.SystemServiceManager;
-import com.android.server.am.MemoryStatUtil.MemoryStat;
-import com.android.server.notification.NotificationManagerService;
-import com.android.server.role.RoleManagerInternal;
-import com.android.server.stats.pull.IonMemoryUtil.IonAllocations;
-import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot;
-import com.android.server.storage.DiskStatsFileLogger;
-import com.android.server.storage.DiskStatsLoggingService;
-
-import com.google.android.collect.Sets;
import libcore.io.IoUtils;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
/**
* Helper service for statsd (the native stats management service in cmds/statsd/).
@@ -178,10 +68,7 @@ import java.util.concurrent.TimeoutException;
* @hide
*/
public class StatsCompanionService extends IStatsCompanionService.Stub {
- /**
- * How long to wait on an individual subsystem to return its stats.
- */
- private static final long EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS = 2000;
+
private static final long MILLIS_IN_A_DAY = TimeUnit.DAYS.toMillis(1);
public static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity";
@@ -201,45 +88,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private static final int INSTALLER_FIELD_ID = 5;
public static final int DEATH_THRESHOLD = 10;
- /**
- * Which native processes to snapshot memory for.
- *
- * <p>Processes are matched by their cmdline in procfs. Example: cat /proc/pid/cmdline returns
- * /system/bin/statsd for the stats daemon.
- */
- private static final Set<String> MEMORY_INTERESTING_NATIVE_PROCESSES = Sets.newHashSet(
- "/system/bin/statsd", // Stats daemon.
- "/system/bin/surfaceflinger",
- "/system/bin/apexd", // APEX daemon.
- "/system/bin/audioserver",
- "/system/bin/cameraserver",
- "/system/bin/drmserver",
- "/system/bin/healthd",
- "/system/bin/incidentd",
- "/system/bin/installd",
- "/system/bin/lmkd", // Low memory killer daemon.
- "/system/bin/logd",
- "media.codec",
- "media.extractor",
- "media.metrics",
- "/system/bin/mediadrmserver",
- "/system/bin/mediaserver",
- "/system/bin/performanced",
- "/system/bin/tombstoned",
- "/system/bin/traced", // Perfetto.
- "/system/bin/traced_probes", // Perfetto.
- "webview_zygote",
- "zygote",
- "zygote64");
- /**
- * Lowest available uid for apps.
- *
- * <p>Used to quickly discard memory snapshots of the zygote forks from native process
- * measurements.
- */
- private static final int MIN_APP_UID = 10_000;
-
- private static final int CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES = 8;
static final class CompanionHandler extends Handler {
CompanionHandler(Looper looper) {
@@ -249,7 +97,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private final Context mContext;
private final AlarmManager mAlarmManager;
- private final INetworkStatsService mNetworkStatsService;
@GuardedBy("sStatsdLock")
private static IStatsd sStatsd;
private static final Object sStatsdLock = new Object();
@@ -263,52 +110,16 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private StatsManagerService mStatsManagerService;
- private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
- private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
- private WifiManager mWifiManager = null;
- private TelephonyManager mTelephony = null;
@GuardedBy("sStatsdLock")
private final HashSet<Long> mDeathTimeMillis = new HashSet<>();
@GuardedBy("sStatsdLock")
private final HashMap<Long, String> mDeletedFiles = new HashMap<>();
private final CompanionHandler mHandler;
- // Disables throttler on CPU time readers.
- private KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader =
- new KernelCpuUidUserSysTimeReader(false);
- private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
- private KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader =
- new KernelCpuUidFreqTimeReader(false);
- private KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader =
- new KernelCpuUidActiveTimeReader(false);
- private KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader =
- new KernelCpuUidClusterTimeReader(false);
- private StoragedUidIoStatsReader mStoragedUidIoStatsReader =
- new StoragedUidIoStatsReader();
- @Nullable
- private final KernelCpuThreadReaderDiff mKernelCpuThreadReader;
-
- private long mDebugElapsedClockPreviousValue = 0;
- private long mDebugElapsedClockPullCount = 0;
- private long mDebugFailingElapsedClockPreviousValue = 0;
- private long mDebugFailingElapsedClockPullCount = 0;
- private BatteryStatsHelper mBatteryStatsHelper = null;
- private static final int MAX_BATTERY_STATS_HELPER_FREQUENCY_MS = 1000;
- private long mBatteryStatsHelperTimestampMs = -MAX_BATTERY_STATS_HELPER_FREQUENCY_MS;
-
- private static IThermalService sThermalService;
- private File mBaseDir =
- new File(SystemServiceManager.ensureSystemDir(), "stats_companion");
- @GuardedBy("this")
- ProcessCpuTracker mProcessCpuTracker = null;
-
public StatsCompanionService(Context context) {
super();
mContext = context;
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
- mNetworkStatsService = INetworkStatsService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
- mBaseDir.mkdirs();
mAppUpdateReceiver = new AppUpdateReceiver();
mUserUpdateReceiver = new BroadcastReceiver() {
@Override
@@ -331,47 +142,10 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
};
mShutdownEventReceiver = new ShutdownEventReceiver();
if (DEBUG) Slog.d(TAG, "Registered receiver for ACTION_PACKAGE_REPLACED and ADDED.");
- PowerProfile powerProfile = new PowerProfile(context);
- final int numClusters = powerProfile.getNumCpuClusters();
- mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
- int firstCpuOfCluster = 0;
- for (int i = 0; i < numClusters; i++) {
- final int numSpeedSteps = powerProfile.getNumSpeedStepsInCpuCluster(i);
- mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
- numSpeedSteps);
- firstCpuOfCluster += powerProfile.getNumCoresInCpuCluster(i);
- }
-
- // Enable push notifications of throttling from vendor thermal
- // management subsystem via thermalservice.
- IBinder b = ServiceManager.getService("thermalservice");
-
- if (b != null) {
- sThermalService = IThermalService.Stub.asInterface(b);
- try {
- sThermalService.registerThermalEventListener(
- new ThermalEventListener());
- Slog.i(TAG, "register thermal listener successfully");
- } catch (RemoteException e) {
- // Should never happen.
- Slog.e(TAG, "register thermal listener error");
- }
- } else {
- Slog.e(TAG, "cannot find thermalservice, no throttling push notifications");
- }
-
- // Default NetworkRequest should cover all transport types.
- final NetworkRequest request = new NetworkRequest.Builder().build();
- final ConnectivityManager connectivityManager =
- (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- connectivityManager.registerNetworkCallback(request, new ConnectivityStatsCallback());
-
HandlerThread handlerThread = new HandlerThread(TAG);
handlerThread.start();
mHandler = new CompanionHandler(handlerThread.getLooper());
- mKernelCpuThreadReader =
- KernelCpuThreadReaderSettingsObserver.getSettingsModifiedReader(mContext);
}
private final static int[] toIntArray(List<Integer> list) {
@@ -855,8 +629,8 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
mDeathTimeMillis.add(now);
if (mDeathTimeMillis.size() >= DEATH_THRESHOLD) {
mDeathTimeMillis.clear();
- File[] configs = FileUtils.listFilesOrEmpty(new File(CONFIG_DIR));
- if (configs.length > 0) {
+ File[] configs = new File(CONFIG_DIR).listFiles();
+ if (configs != null && configs.length > 0) {
String fileName = configs[0].getName();
if (configs[0].delete()) {
mDeletedFiles.put(now, fileName);
@@ -909,28 +683,4 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
}
}
-
- // Thermal event received from vendor thermal management subsystem
- private static final class ThermalEventListener extends IThermalEventListener.Stub {
- @Override
- public void notifyThrottling(Temperature temp) {
- StatsLog.write(StatsLog.THERMAL_THROTTLING_SEVERITY_STATE_CHANGED, temp.getType(),
- temp.getName(), (int) (temp.getValue() * 10), temp.getStatus());
- }
- }
-
- private static final class ConnectivityStatsCallback extends
- ConnectivityManager.NetworkCallback {
- @Override
- public void onAvailable(Network network) {
- StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId,
- StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__CONNECTED);
- }
-
- @Override
- public void onLost(Network network) {
- StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId,
- StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__DISCONNECTED);
- }
- }
}
diff --git a/api/current.txt b/api/current.txt
index 326ae6b54b0b..4ab54b3654b8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3901,6 +3901,7 @@ package android.app {
method public void setImmersive(boolean);
method public void setInheritShowWhenLocked(boolean);
method public void setIntent(android.content.Intent);
+ method public void setLocusContext(@Nullable android.content.LocusId, @Nullable android.os.Bundle);
method public final void setMediaController(android.media.session.MediaController);
method public void setPictureInPictureParams(@NonNull android.app.PictureInPictureParams);
method @Deprecated public final void setProgress(int);
@@ -6918,6 +6919,7 @@ package android.app.admin {
method public boolean removeOverrideApn(@NonNull android.content.ComponentName, int);
method public boolean removeUser(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
method public boolean requestBugreport(@NonNull android.content.ComponentName);
+ method public void requestSetLocationProviderAllowed(@NonNull android.content.ComponentName, @NonNull String, boolean);
method @Deprecated public boolean resetPassword(String, int);
method public boolean resetPasswordWithToken(@NonNull android.content.ComponentName, String, byte[], int);
method @Nullable public java.util.List<android.app.admin.NetworkEvent> retrieveNetworkLogs(@Nullable android.content.ComponentName, long);
@@ -16737,6 +16739,7 @@ package android.hardware {
field public static final String STRING_TYPE_GYROSCOPE_UNCALIBRATED = "android.sensor.gyroscope_uncalibrated";
field public static final String STRING_TYPE_HEART_BEAT = "android.sensor.heart_beat";
field public static final String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";
+ field public static final String STRING_TYPE_HINGE_ANGLE = "android.sensor.hinge_angle";
field public static final String STRING_TYPE_LIGHT = "android.sensor.light";
field public static final String STRING_TYPE_LINEAR_ACCELERATION = "android.sensor.linear_acceleration";
field public static final String STRING_TYPE_LOW_LATENCY_OFFBODY_DETECT = "android.sensor.low_latency_offbody_detect";
@@ -16766,6 +16769,7 @@ package android.hardware {
field public static final int TYPE_GYROSCOPE_UNCALIBRATED = 16; // 0x10
field public static final int TYPE_HEART_BEAT = 31; // 0x1f
field public static final int TYPE_HEART_RATE = 21; // 0x15
+ field public static final int TYPE_HINGE_ANGLE = 36; // 0x24
field public static final int TYPE_LIGHT = 5; // 0x5
field public static final int TYPE_LINEAR_ACCELERATION = 10; // 0xa
field public static final int TYPE_LOW_LATENCY_OFFBODY_DETECT = 34; // 0x22
@@ -25986,6 +25990,7 @@ package android.media {
field public static final String KEY_CAPTURE_RATE = "capture-rate";
field public static final String KEY_CHANNEL_COUNT = "channel-count";
field public static final String KEY_CHANNEL_MASK = "channel-mask";
+ field public static final String KEY_CODECS_STRING = "codecs-string";
field public static final String KEY_COLOR_FORMAT = "color-format";
field public static final String KEY_COLOR_RANGE = "color-range";
field public static final String KEY_COLOR_STANDARD = "color-standard";
@@ -30046,6 +30051,7 @@ package android.net {
method public int getLinkDownstreamBandwidthKbps();
method public int getLinkUpstreamBandwidthKbps();
method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
+ method public int getOwnerUid();
method public int getSignalStrength();
method @Nullable public android.net.TransportInfo getTransportInfo();
method public boolean hasCapability(int);
@@ -30055,6 +30061,7 @@ package android.net {
method @NonNull public android.net.NetworkCapabilities setLinkDownstreamBandwidthKbps(int);
method @NonNull public android.net.NetworkCapabilities setLinkUpstreamBandwidthKbps(int);
method @NonNull public android.net.NetworkCapabilities setNetworkSpecifier(@NonNull android.net.NetworkSpecifier);
+ method public void setOwnerUid(int);
method @NonNull public android.net.NetworkCapabilities setSignalStrength(int);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkCapabilities> CREATOR;
diff --git a/api/system-current.txt b/api/system-current.txt
index b4825bfe3695..5691bf3fddbc 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1830,6 +1830,7 @@ package android.content {
field @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public static final String ACTION_MANAGE_SPECIAL_APP_ACCESSES = "android.intent.action.MANAGE_SPECIAL_APP_ACCESSES";
field public static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
field public static final String ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_INTEGRITY_VERIFICATION";
+ field public static final String ACTION_PACKAGE_UNSUSPENDED_MANUALLY = "android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY";
field public static final String ACTION_PENDING_INCIDENT_REPORTS_CHANGED = "android.intent.action.PENDING_INCIDENT_REPORTS_CHANGED";
field public static final String ACTION_PRE_BOOT_COMPLETED = "android.intent.action.PRE_BOOT_COMPLETED";
field public static final String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART";
@@ -1898,26 +1899,6 @@ package android.content {
package android.content.integrity {
- public final class AppInstallMetadata {
- method @NonNull public String getAppCertificate();
- method @Nullable public String getInstallerCertificate();
- method @Nullable public String getInstallerName();
- method @NonNull public String getPackageName();
- method public int getVersionCode();
- method public boolean isPreInstalled();
- }
-
- public static final class AppInstallMetadata.Builder {
- ctor public AppInstallMetadata.Builder();
- method @NonNull public android.content.integrity.AppInstallMetadata build();
- method @NonNull public android.content.integrity.AppInstallMetadata.Builder setAppCertificate(@NonNull String);
- method @NonNull public android.content.integrity.AppInstallMetadata.Builder setInstallerCertificate(@NonNull String);
- method @NonNull public android.content.integrity.AppInstallMetadata.Builder setInstallerName(@NonNull String);
- method @NonNull public android.content.integrity.AppInstallMetadata.Builder setIsPreInstalled(boolean);
- method @NonNull public android.content.integrity.AppInstallMetadata.Builder setPackageName(@NonNull String);
- method @NonNull public android.content.integrity.AppInstallMetadata.Builder setVersionCode(int);
- }
-
public class AppIntegrityManager {
method @NonNull public String getCurrentRuleSetProvider();
method @NonNull public String getCurrentRuleSetVersion();
@@ -1927,84 +1908,28 @@ package android.content.integrity {
field public static final int STATUS_SUCCESS = 0; // 0x0
}
- public abstract class AtomicFormula implements android.content.integrity.Formula {
- ctor public AtomicFormula(int);
- method public int getKey();
- field public static final int APP_CERTIFICATE = 1; // 0x1
- field public static final int EQ = 0; // 0x0
- field public static final int GE = 4; // 0x4
- field public static final int GT = 3; // 0x3
- field public static final int INSTALLER_CERTIFICATE = 3; // 0x3
- field public static final int INSTALLER_NAME = 2; // 0x2
- field public static final int LE = 2; // 0x2
- field public static final int LT = 1; // 0x1
- field public static final int PACKAGE_NAME = 0; // 0x0
- field public static final int PRE_INSTALLED = 5; // 0x5
- field public static final int VERSION_CODE = 4; // 0x4
- }
-
- public static final class AtomicFormula.BooleanAtomicFormula extends android.content.integrity.AtomicFormula implements android.os.Parcelable {
- ctor public AtomicFormula.BooleanAtomicFormula(int, boolean);
- method public int describeContents();
- method public int getTag();
- method public boolean getValue();
- method public boolean isSatisfied(@NonNull android.content.integrity.AppInstallMetadata);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.AtomicFormula.BooleanAtomicFormula> CREATOR;
- }
-
- public static final class AtomicFormula.IntAtomicFormula extends android.content.integrity.AtomicFormula implements android.os.Parcelable {
- ctor public AtomicFormula.IntAtomicFormula(int, int, int);
- method public int describeContents();
- method public int getOperator();
- method public int getTag();
- method public int getValue();
- method public boolean isSatisfied(@NonNull android.content.integrity.AppInstallMetadata);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.AtomicFormula.IntAtomicFormula> CREATOR;
- }
-
- public static final class AtomicFormula.StringAtomicFormula extends android.content.integrity.AtomicFormula implements android.os.Parcelable {
- ctor public AtomicFormula.StringAtomicFormula(int, @NonNull String, boolean);
- method public int describeContents();
- method public boolean getIsHashedValue();
- method public int getTag();
- method @NonNull public String getValue();
- method public boolean isSatisfied(@NonNull android.content.integrity.AppInstallMetadata);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.AtomicFormula.StringAtomicFormula> CREATOR;
- }
-
- public final class CompoundFormula implements android.content.integrity.Formula android.os.Parcelable {
- ctor public CompoundFormula(int, @NonNull java.util.List<android.content.integrity.Formula>);
- method public int describeContents();
- method public int getConnector();
- method @NonNull public java.util.List<android.content.integrity.Formula> getFormulas();
- method public int getTag();
- method public boolean isSatisfied(@NonNull android.content.integrity.AppInstallMetadata);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int AND = 0; // 0x0
- field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.CompoundFormula> CREATOR;
- field public static final int NOT = 2; // 0x2
- field public static final int OR = 1; // 0x1
- }
-
- public interface Formula {
- method public int getTag();
- method public boolean isSatisfied(@NonNull android.content.integrity.AppInstallMetadata);
- method @NonNull public static android.content.integrity.Formula readFromParcel(@NonNull android.os.Parcel);
- method public static void writeToParcel(@NonNull android.content.integrity.Formula, @NonNull android.os.Parcel, int);
- field public static final int BOOLEAN_ATOMIC_FORMULA_TAG = 3; // 0x3
- field public static final int COMPOUND_FORMULA_TAG = 0; // 0x0
- field public static final int INT_ATOMIC_FORMULA_TAG = 2; // 0x2
- field public static final int STRING_ATOMIC_FORMULA_TAG = 1; // 0x1
+ public abstract class IntegrityFormula {
+ method @NonNull public static android.content.integrity.IntegrityFormula all(@NonNull android.content.integrity.IntegrityFormula...);
+ method @NonNull public static android.content.integrity.IntegrityFormula any(@NonNull android.content.integrity.IntegrityFormula...);
+ method @NonNull public android.content.integrity.IntegrityFormula equalTo(@NonNull String);
+ method @NonNull public android.content.integrity.IntegrityFormula equalTo(boolean);
+ method @NonNull public android.content.integrity.IntegrityFormula equalTo(long);
+ method @NonNull public android.content.integrity.IntegrityFormula greaterThan(long);
+ method @NonNull public android.content.integrity.IntegrityFormula greaterThanOrEquals(long);
+ method @NonNull public static android.content.integrity.IntegrityFormula not(@NonNull android.content.integrity.IntegrityFormula);
+ field @NonNull public static final android.content.integrity.IntegrityFormula APP_CERTIFICATE;
+ field @NonNull public static final android.content.integrity.IntegrityFormula INSTALLER_CERTIFICATE;
+ field @NonNull public static final android.content.integrity.IntegrityFormula INSTALLER_NAME;
+ field @NonNull public static final android.content.integrity.IntegrityFormula PACKAGE_NAME;
+ field @NonNull public static final android.content.integrity.IntegrityFormula PRE_INSTALLED;
+ field @NonNull public static final android.content.integrity.IntegrityFormula VERSION_CODE;
}
public final class Rule implements android.os.Parcelable {
- ctor public Rule(@NonNull android.content.integrity.Formula, int);
+ ctor public Rule(@NonNull android.content.integrity.IntegrityFormula, int);
method public int describeContents();
method public int getEffect();
- method @NonNull public android.content.integrity.Formula getFormula();
+ method @NonNull public android.content.integrity.IntegrityFormula getFormula();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.content.integrity.Rule> CREATOR;
field public static final int DENY = 0; // 0x0
@@ -2042,8 +1967,8 @@ package android.content.om {
public class OverlayManager {
method @Nullable public android.content.om.OverlayInfo getOverlayInfo(@NonNull String, @NonNull android.os.UserHandle);
method @NonNull @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public java.util.List<android.content.om.OverlayInfo> getOverlayInfosForTarget(@NonNull String, @NonNull android.os.UserHandle);
- method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public void setEnabled(@NonNull String, boolean, @NonNull android.os.UserHandle);
- method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public void setEnabledExclusiveInCategory(@NonNull String, @NonNull android.os.UserHandle);
+ method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public void setEnabled(@NonNull String, boolean, @NonNull android.os.UserHandle) throws java.lang.IllegalStateException, java.lang.SecurityException;
+ method @RequiresPermission(anyOf={"android.permission.INTERACT_ACROSS_USERS", "android.permission.INTERACT_ACROSS_USERS_FULL"}) public void setEnabledExclusiveInCategory(@NonNull String, @NonNull android.os.UserHandle) throws java.lang.IllegalStateException, java.lang.SecurityException;
}
}
@@ -2259,6 +2184,7 @@ package android.content.pm {
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] setPackagesSuspended(@Nullable String[], boolean, @Nullable android.os.PersistableBundle, @Nullable android.os.PersistableBundle, @Nullable String);
method @Nullable @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] setPackagesSuspended(@Nullable String[], boolean, @Nullable android.os.PersistableBundle, @Nullable android.os.PersistableBundle, @Nullable android.content.pm.SuspendDialogInfo);
method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public void setSyntheticAppDetailsActivityEnabled(@NonNull String, boolean);
+ method public void setSystemAppState(@NonNull String, int);
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public abstract void setUpdateAvailable(@NonNull String, boolean);
method @RequiresPermission(android.Manifest.permission.SET_PREFERRED_APPLICATIONS) public abstract boolean updateIntentVerificationStatusAsUser(@NonNull String, int, int);
method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS}) public abstract void updatePermissionFlags(@NonNull String, @NonNull String, @android.content.pm.PackageManager.PermissionFlags int, @android.content.pm.PackageManager.PermissionFlags int, @NonNull android.os.UserHandle);
@@ -2339,6 +2265,10 @@ package android.content.pm {
field public static final int RESTRICTION_HIDE_FROM_SUGGESTIONS = 1; // 0x1
field public static final int RESTRICTION_HIDE_NOTIFICATIONS = 2; // 0x2
field public static final int RESTRICTION_NONE = 0; // 0x0
+ field public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN = 0; // 0x0
+ field public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_VISIBLE = 1; // 0x1
+ field public static final int SYSTEM_APP_STATE_INSTALLED = 2; // 0x2
+ field public static final int SYSTEM_APP_STATE_UNINSTALLED = 3; // 0x3
}
public abstract static class PackageManager.DexModuleRegisterCallback {
@@ -2399,6 +2329,8 @@ package android.content.pm {
public final class SuspendDialogInfo implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
+ field public static final int BUTTON_ACTION_MORE_DETAILS = 0; // 0x0
+ field public static final int BUTTON_ACTION_UNSUSPEND = 1; // 0x1
field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.SuspendDialogInfo> CREATOR;
}
@@ -2408,6 +2340,7 @@ package android.content.pm {
method @NonNull public android.content.pm.SuspendDialogInfo.Builder setIcon(@DrawableRes int);
method @NonNull public android.content.pm.SuspendDialogInfo.Builder setMessage(@NonNull String);
method @NonNull public android.content.pm.SuspendDialogInfo.Builder setMessage(@StringRes int);
+ method @NonNull public android.content.pm.SuspendDialogInfo.Builder setNeutralButtonAction(int);
method @NonNull public android.content.pm.SuspendDialogInfo.Builder setNeutralButtonText(@StringRes int);
method @NonNull public android.content.pm.SuspendDialogInfo.Builder setTitle(@StringRes int);
}
@@ -8411,7 +8344,7 @@ package android.os {
method @NonNull public android.os.BatterySaverPolicyConfig.Builder setLocationMode(int);
}
- public final class BatteryStatsManager {
+ public class BatteryStatsManager {
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.CellularBatteryStats getCellularBatteryStats();
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.WifiBatteryStats getWifiBatteryStats();
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockAcquiredFromSource(@NonNull android.os.WorkSource);
@@ -8891,7 +8824,6 @@ package android.os {
method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getEuiccControllerService();
method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getIccPhoneBookServiceRegisterer();
method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getOpportunisticNetworkServiceRegisterer();
- method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getPackageManagerServiceRegisterer();
method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getPhoneSubServiceRegisterer();
method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getSmsServiceRegisterer();
method @NonNull public android.os.TelephonyServiceManager.ServiceRegisterer getSubscriptionServiceRegisterer();
@@ -9232,6 +9164,7 @@ package android.permission {
public final class PermissionManager {
method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY) public int getRuntimePermissionsVersion();
method @NonNull public java.util.List<android.permission.PermissionManager.SplitPermissionInfo> getSplitPermissions();
+ method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) public void grantDefaultPermissionsToEnabledCarrierApps(@NonNull String[], @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) public void grantDefaultPermissionsToEnabledImsServices(@NonNull String[], @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) public void grantDefaultPermissionsToEnabledTelephonyDataServices(@NonNull String[], @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) public void grantDefaultPermissionsToLuiApp(@NonNull String, @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
@@ -12270,6 +12203,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetAllCarrierActions();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption();
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void resetIms(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig();
method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d952be5218a4..d8b5e7f3b5b0 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -45,6 +45,7 @@ import android.content.CursorLoader;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.LocusId;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -1025,6 +1026,39 @@ public class Activity extends ContextThemeWrapper
mIntent = newIntent;
}
+ /**
+ * Sets the {@link android.content.LocusId} for this activity. The locus id
+ * helps identify different instances of the same {@code Activity} class.
+ * <p> For example, a locus id based on a specific conversation could be set on a
+ * conversation app's chat {@code Activity}. The system can then use this locus id
+ * along with app's contents to provide ranking signals in various UI surfaces
+ * including sharing, notifications, shortcuts and so on.
+ * <p> It is recommended to set the same locus id in the shortcut's locus id using
+ * {@link android.content.pm.ShortcutInfo.Builder#setLocusId(android.content.LocusId)
+ * setLocusId}
+ * so that the system can learn appropriate ranking signals linking the activity's
+ * locus id with the matching shortcut.
+ *
+ * @param locusId a unique, stable id that identifies this {@code Activity} instance from
+ * others. This can be linked to a shortcut using
+ * {@link android.content.pm.ShortcutInfo.Builder#setLocusId(android.content.LocusId)
+ * setLocusId} with the same locus id string.
+ * @param bundle extras set or updated as part of this locus context. This may help provide
+ * additional metadata such as URLs, conversation participants specific to this
+ * {@code Activity}'s context.
+ *
+ * @see android.view.contentcapture.ContentCaptureManager
+ * @see android.view.contentcapture.ContentCaptureContext
+ */
+ public void setLocusContext(@Nullable LocusId locusId, @Nullable Bundle bundle) {
+ try {
+ ActivityManager.getService().setActivityLocusContext(mComponent, locusId, mToken);
+ } catch (RemoteException re) {
+ re.rethrowFromSystemServer();
+ }
+ // TODO(b/147750355): Pass locusId and bundle to the Content Capture.
+ }
+
/** Return the application that owns this activity. */
public final Application getApplication() {
return mApplication;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index f7c4d96d0d40..e0a4ae287408 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -73,6 +73,7 @@ import android.util.DisplayMetrics;
import android.util.Singleton;
import android.util.Size;
import android.view.IWindowContainer;
+import android.view.Surface;
import com.android.internal.app.LocalePicker;
import com.android.internal.app.procstats.ProcessStats;
@@ -1928,7 +1929,12 @@ public class ActivityManager {
// Top activity in task when snapshot was taken
private final ComponentName mTopActivityComponent;
private final GraphicBuffer mSnapshot;
+ /** Indicates whether task was in landscape or portrait */
+ @Configuration.Orientation
private final int mOrientation;
+ /** See {@link android.view.Surface.Rotation} */
+ @Surface.Rotation
+ private int mRotation;
private final Rect mContentInsets;
// Whether this snapshot is a down-sampled version of the full resolution, used mainly for
// low-ram devices
@@ -1945,7 +1951,7 @@ public class ActivityManager {
public TaskSnapshot(long id,
@NonNull ComponentName topActivityComponent, GraphicBuffer snapshot,
- @NonNull ColorSpace colorSpace, int orientation, Rect contentInsets,
+ @NonNull ColorSpace colorSpace, int orientation, int rotation, Rect contentInsets,
boolean reducedResolution, float scale, boolean isRealSnapshot, int windowingMode,
int systemUiVisibility, boolean isTranslucent) {
mId = id;
@@ -1954,6 +1960,7 @@ public class ActivityManager {
mColorSpace = colorSpace.getId() < 0
? ColorSpace.get(ColorSpace.Named.SRGB) : colorSpace;
mOrientation = orientation;
+ mRotation = rotation;
mContentInsets = new Rect(contentInsets);
mReducedResolution = reducedResolution;
mScale = scale;
@@ -1972,6 +1979,7 @@ public class ActivityManager {
? ColorSpace.get(ColorSpace.Named.values()[colorSpaceId])
: ColorSpace.get(ColorSpace.Named.SRGB);
mOrientation = source.readInt();
+ mRotation = source.readInt();
mContentInsets = source.readParcelable(null /* classLoader */);
mReducedResolution = source.readBoolean();
mScale = source.readFloat();
@@ -2019,6 +2027,13 @@ public class ActivityManager {
}
/**
+ * @return The screen rotation the screenshot was taken in.
+ */
+ public int getRotation() {
+ return mRotation;
+ }
+
+ /**
* @return The system/content insets on the snapshot. These can be clipped off in order to
* remove any areas behind system bars in the snapshot.
*/
@@ -2087,6 +2102,7 @@ public class ActivityManager {
dest.writeParcelable(mSnapshot, 0);
dest.writeInt(mColorSpace.getId());
dest.writeInt(mOrientation);
+ dest.writeInt(mRotation);
dest.writeParcelable(mContentInsets, 0);
dest.writeBoolean(mReducedResolution);
dest.writeFloat(mScale);
@@ -2106,6 +2122,7 @@ public class ActivityManager {
+ " mSnapshot=" + mSnapshot + " (" + width + "x" + height + ")"
+ " mColorSpace=" + mColorSpace.toString()
+ " mOrientation=" + mOrientation
+ + " mRotation=" + mRotation
+ " mContentInsets=" + mContentInsets.toShortString()
+ " mReducedResolution=" + mReducedResolution + " mScale=" + mScale
+ " mIsRealSnapshot=" + mIsRealSnapshot + " mWindowingMode=" + mWindowingMode
@@ -2129,6 +2146,7 @@ public class ActivityManager {
private GraphicBuffer mSnapshot;
private ColorSpace mColorSpace;
private int mOrientation;
+ private int mRotation;
private Rect mContentInsets;
private boolean mReducedResolution;
private float mScaleFraction;
@@ -2163,6 +2181,11 @@ public class ActivityManager {
return this;
}
+ public Builder setRotation(int rotation) {
+ mRotation = rotation;
+ return this;
+ }
+
public Builder setContentInsets(Rect contentInsets) {
mContentInsets = contentInsets;
return this;
@@ -2218,6 +2241,7 @@ public class ActivityManager {
mSnapshot,
mColorSpace,
mOrientation,
+ mRotation,
mContentInsets,
mReducedResolution,
mScaleFraction,
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 4e6319db97f4..c09aa1ff05a8 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -131,7 +131,7 @@ public class ApplicationPackageManager extends PackageManager {
private static final int DEFAULT_EPHEMERAL_COOKIE_MAX_SIZE_BYTES = 16384; // 16KB
// Default flags to use with PackageManager when no flags are given.
- private final static int sDefaultFlags = PackageManager.GET_SHARED_LIBRARY_FILES;
+ private static final int sDefaultFlags = GET_SHARED_LIBRARY_FILES;
// Name of the resource which provides background permission button string
public static final String APP_PERMISSION_BUTTON_ALLOW_ALWAYS =
@@ -907,7 +907,7 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public boolean hasSigningCertificate(
- String packageName, byte[] certificate, @PackageManager.CertificateInputType int type) {
+ String packageName, byte[] certificate, @CertificateInputType int type) {
try {
return mPM.hasSigningCertificate(packageName, certificate, type);
} catch (RemoteException e) {
@@ -917,7 +917,7 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public boolean hasSigningCertificate(
- int uid, byte[] certificate, @PackageManager.CertificateInputType int type) {
+ int uid, byte[] certificate, @CertificateInputType int type) {
try {
return mPM.hasUidSigningCertificate(uid, certificate, type);
} catch (RemoteException e) {
@@ -1464,8 +1464,7 @@ public class ApplicationPackageManager extends PackageManager {
return getActivityIcon(intent.getComponent());
}
- ResolveInfo info = resolveActivity(
- intent, PackageManager.MATCH_DEFAULT_ONLY);
+ ResolveInfo info = resolveActivity(intent, MATCH_DEFAULT_ONLY);
if (info != null) {
return info.activityInfo.loadIcon(this);
}
@@ -1500,7 +1499,7 @@ public class ApplicationPackageManager extends PackageManager {
}
ResolveInfo info = resolveActivity(
- intent, PackageManager.MATCH_DEFAULT_ONLY);
+ intent, MATCH_DEFAULT_ONLY);
if (info != null) {
return info.activityInfo.loadBanner(this);
}
@@ -1532,8 +1531,7 @@ public class ApplicationPackageManager extends PackageManager {
return getActivityLogo(intent.getComponent());
}
- ResolveInfo info = resolveActivity(
- intent, PackageManager.MATCH_DEFAULT_ONLY);
+ ResolveInfo info = resolveActivity(intent, MATCH_DEFAULT_ONLY);
if (info != null) {
return info.activityInfo.loadLogo(this);
}
@@ -2017,7 +2015,7 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public int installExistingPackage(String packageName) throws NameNotFoundException {
- return installExistingPackage(packageName, PackageManager.INSTALL_REASON_UNKNOWN);
+ return installExistingPackage(packageName, INSTALL_REASON_UNKNOWN);
}
@Override
@@ -2029,7 +2027,7 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public int installExistingPackageAsUser(String packageName, int userId)
throws NameNotFoundException {
- return installExistingPackageAsUser(packageName, PackageManager.INSTALL_REASON_UNKNOWN,
+ return installExistingPackageAsUser(packageName, INSTALL_REASON_UNKNOWN,
userId);
}
@@ -2404,7 +2402,7 @@ public class ApplicationPackageManager extends PackageManager {
public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer,
int flags, int userId) {
try {
- mPM.deletePackageAsUser(packageName, PackageManager.VERSION_CODE_HIGHEST,
+ mPM.deletePackageAsUser(packageName, VERSION_CODE_HIGHEST,
observer, userId, flags);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -2651,11 +2649,11 @@ public class ApplicationPackageManager extends PackageManager {
public void setSyntheticAppDetailsActivityEnabled(String packageName, boolean enabled) {
try {
ComponentName componentName = new ComponentName(packageName,
- PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME);
+ APP_DETAILS_ACTIVITY_CLASS_NAME);
mPM.setComponentEnabledSetting(componentName, enabled
- ? PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
- : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP, getUserId());
+ ? COMPONENT_ENABLED_STATE_DEFAULT
+ : COMPONENT_ENABLED_STATE_DISABLED,
+ DONT_KILL_APP, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2665,10 +2663,10 @@ public class ApplicationPackageManager extends PackageManager {
public boolean getSyntheticAppDetailsActivityEnabled(String packageName) {
try {
ComponentName componentName = new ComponentName(packageName,
- PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME);
+ APP_DETAILS_ACTIVITY_CLASS_NAME);
int state = mPM.getComponentEnabledSetting(componentName, getUserId());
- return state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
- || state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+ return state == COMPONENT_ENABLED_STATE_ENABLED
+ || state == COMPONENT_ENABLED_STATE_DEFAULT;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2744,6 +2742,30 @@ public class ApplicationPackageManager extends PackageManager {
/** @hide */
@Override
+ public void setSystemAppState(String packageName, @SystemAppState int state) {
+ try {
+ switch (state) {
+ case SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN:
+ mPM.setSystemAppHiddenUntilInstalled(packageName, true);
+ break;
+ case SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_VISIBLE:
+ mPM.setSystemAppHiddenUntilInstalled(packageName, false);
+ break;
+ case SYSTEM_APP_STATE_INSTALLED:
+ mPM.setSystemAppInstallState(packageName, true, getUserId());
+ break;
+ case SYSTEM_APP_STATE_UNINSTALLED:
+ mPM.setSystemAppInstallState(packageName, false, getUserId());
+ break;
+ default:
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** @hide */
+ @Override
public KeySet getKeySetByAlias(String packageName, String alias) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(alias);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 7d04ca0afe7e..3ffd7c70b40d 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -53,6 +53,7 @@ import android.content.pm.ParceledListSlice;
import android.content.pm.ProviderInfo;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
+import android.content.LocusId;
import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
import android.graphics.Point;
@@ -637,4 +638,13 @@ interface IActivityManager {
* and the given process is imperceptible.
*/
void killProcessesWhenImperceptible(in int[] pids, String reason);
+
+ /**
+ * Set locus context for a given activity.
+ * @param activity
+ * @param locusId a unique, stable id that identifies this activity instance from others.
+ * @param appToken ActivityRecord's appToken.
+ */
+ void setActivityLocusContext(in ComponentName activity, in LocusId locusId,
+ in IBinder appToken);
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index f4dc0bffd5ed..d1b5a83e7142 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -8855,6 +8855,49 @@ public class DevicePolicyManager {
}
/**
+ * Called by device owners to request a location provider to change its allowed state. For a
+ * provider to be enabled requires both that the master location setting is enabled, and that
+ * the provider itself is allowed. Most location providers are always allowed. Some location
+ * providers may have user consents or terms and conditions that must be accepted, or some other
+ * type of blocker before they are allowed however. Every location provider is responsible for
+ * its own allowed state.
+ *
+ * <p>This method requests that a location provider change its allowed state. For providers that
+ * are always allowed and have no state to change, this will have no effect. If the provider
+ * does require some consent, terms and conditions, or other blocking state, using this API
+ * implies that the device owner is agreeing/disagreeing to any consents, terms and conditions,
+ * etc, and the provider should make a best effort to adjust it's allowed state accordingly.
+ *
+ * <p>Location providers are generally only responsible for the current user, and callers must
+ * assume that this method will only affect provider state for the current user. Callers are
+ * responsible for tracking current user changes and re-updating provider state as necessary.
+ *
+ * <p>While providers are expected to make a best effort to honor this request, it is not a
+ * given that all providers will support such a request. If a provider does change its state as
+ * a result of this request, that may happen asynchronously after some delay. Test location
+ * providers set through {@link android.location.LocationManager#addTestProvider} will respond
+ * to this request to aide in testing.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with
+ * @param provider A location provider as listed by
+ * {@link android.location.LocationManager#getAllProviders()}
+ * @param providerAllowed Whether the location provider is being requested to enable or disable
+ * itself
+ * @throws SecurityException if {@code admin} is not a device owner.
+ */
+ public void requestSetLocationProviderAllowed(@NonNull ComponentName admin,
+ @NonNull String provider, boolean providerAllowed) {
+ throwIfParentInstance("requestSetLocationProviderAllowed");
+ if (mService != null) {
+ try {
+ mService.requestSetLocationProviderAllowed(admin, provider, providerAllowed);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
+ /**
* Called by profile or device owners to update {@link android.provider.Settings.Secure}
* settings. Validation that the value of the setting is in the correct form for the setting
* type should be performed by the caller.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index ab0598b76b82..e3dba310ab44 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -270,6 +270,7 @@ interface IDevicePolicyManager {
boolean isLockdownAdminConfiguredNetworks(in ComponentName who);
void setLocationEnabled(in ComponentName who, boolean locationEnabled);
+ void requestSetLocationProviderAllowed(in ComponentName who, in String provider, boolean providerAllowed);
boolean setTime(in ComponentName who, long millis);
boolean setTimeZone(in ComponentName who, String timeZone);
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 6ab880dfb36d..ab71e73fd58c 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -290,10 +290,16 @@ public final class UsageEvents implements Parcelable {
public static final int USER_STOPPED = 29;
/**
+ * An event type denoting that new locusId has been set for a given activity.
+ * @hide
+ */
+ public static final int LOCUS_ID_SET = 30;
+
+ /**
* Keep in sync with the greatest event type value.
* @hide
*/
- public static final int MAX_EVENT_TYPE = 29;
+ public static final int MAX_EVENT_TYPE = 30;
/** @hide */
public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
@@ -436,6 +442,18 @@ public final class UsageEvents implements Parcelable {
*/
public int mNotificationChannelIdToken = UNASSIGNED_TOKEN;
+ /**
+ * LocusId.
+ * Currently LocusId only present for {@link #LOCUS_ID_SET} event types.
+ * {@hide}
+ */
+ public String mLocusId;
+
+ /**
+ * {@hide}
+ */
+ public int mLocusIdToken = UNASSIGNED_TOKEN;
+
/** @hide */
@EventFlags
public int mFlags;
@@ -609,6 +627,16 @@ public final class UsageEvents implements Parcelable {
return ret;
}
+ /**
+ * Returns the locusId for this event if the event is of type {@link #LOCUS_ID_SET},
+ * otherwise it returns null.
+ * @hide
+ */
+ @Nullable
+ public String getLocusId() {
+ return mLocusId;
+ }
+
private void copyFrom(Event orig) {
mPackage = orig.mPackage;
mClass = orig.mClass;
@@ -625,6 +653,7 @@ public final class UsageEvents implements Parcelable {
mFlags = orig.mFlags;
mBucketAndReason = orig.mBucketAndReason;
mNotificationChannelId = orig.mNotificationChannelId;
+ mLocusId = orig.mLocusId;
}
}
@@ -823,6 +852,9 @@ public final class UsageEvents implements Parcelable {
case Event.NOTIFICATION_INTERRUPTION:
p.writeString(event.mNotificationChannelId);
break;
+ case Event.LOCUS_ID_SET:
+ p.writeString(event.mLocusId);
+ break;
}
p.writeInt(event.mFlags);
}
@@ -871,6 +903,7 @@ public final class UsageEvents implements Parcelable {
eventOut.mContentType = null;
eventOut.mContentAnnotations = null;
eventOut.mNotificationChannelId = null;
+ eventOut.mLocusId = null;
switch (eventOut.mEventType) {
case Event.CONFIGURATION_CHANGE:
@@ -891,6 +924,9 @@ public final class UsageEvents implements Parcelable {
case Event.NOTIFICATION_INTERRUPTION:
eventOut.mNotificationChannelId = p.readString();
break;
+ case Event.LOCUS_ID_SET:
+ eventOut.mLocusId = p.readString();
+ break;
}
eventOut.mFlags = p.readInt();
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 5852a93ea221..a07625315a2d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -36,6 +36,7 @@ import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
+import android.content.pm.SuspendDialogInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Rect;
@@ -2667,6 +2668,34 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.action.SHOW_SUSPENDED_APP_DETAILS";
/**
+ * Broadcast Action: Sent to indicate that the user unsuspended a package.
+ *
+ * <p>This can happen when the user taps on the neutral button of the
+ * {@linkplain SuspendDialogInfo suspend-dialog} which was created by using
+ * {@link SuspendDialogInfo#BUTTON_ACTION_UNSUSPEND}. This broadcast is only sent to the
+ * suspending app that originally specified this dialog while calling
+ * {@link PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
+ * PersistableBundle, SuspendDialogInfo)}.
+ *
+ * <p>Includes an extra {@link #EXTRA_PACKAGE_NAME} which is the name of the package that just
+ * got unsuspended.
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system. <em>This will be delivered to {@link BroadcastReceiver} components declared in
+ * the manifest.</em>
+ *
+ * @see PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
+ * PersistableBundle, SuspendDialogInfo)
+ * @see PackageManager#isPackageSuspended()
+ * @see SuspendDialogInfo#BUTTON_ACTION_MORE_DETAILS
+ * @hide
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_PACKAGE_UNSUSPENDED_MANUALLY =
+ "android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY";
+
+ /**
* Broadcast Action: Sent to a package that has been unsuspended.
*
* <p class="note">This is a protected intent that can only be sent
diff --git a/core/java/android/content/LocusId.aidl b/core/java/android/content/LocusId.aidl
new file mode 100644
index 000000000000..eb98db06ccbf
--- /dev/null
+++ b/core/java/android/content/LocusId.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2020, 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.content;
+
+parcelable LocusId;
diff --git a/core/java/android/content/integrity/AppInstallMetadata.java b/core/java/android/content/integrity/AppInstallMetadata.java
index 85af8813fa94..351edc92888d 100644
--- a/core/java/android/content/integrity/AppInstallMetadata.java
+++ b/core/java/android/content/integrity/AppInstallMetadata.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -17,10 +17,6 @@
package android.content.integrity;
import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-
-import com.android.internal.annotations.VisibleForTesting;
import java.util.Objects;
@@ -34,8 +30,6 @@ import java.util.Objects;
*
* @hide
*/
-@SystemApi
-@VisibleForTesting
public final class AppInstallMetadata {
private final String mPackageName;
// Raw string encoding for the SHA-256 hash of the certificate of the app.
@@ -43,7 +37,7 @@ public final class AppInstallMetadata {
private final String mInstallerName;
// Raw string encoding for the SHA-256 hash of the certificate of the installer.
private final String mInstallerCertificate;
- private final int mVersionCode;
+ private final long mVersionCode;
private final boolean mIsPreInstalled;
private AppInstallMetadata(Builder builder) {
@@ -65,18 +59,18 @@ public final class AppInstallMetadata {
return mAppCertificate;
}
- @Nullable
+ @NonNull
public String getInstallerName() {
return mInstallerName;
}
- @Nullable
+ @NonNull
public String getInstallerCertificate() {
return mInstallerCertificate;
}
- /** @see AppInstallMetadata.Builder#setVersionCode(int) */
- public int getVersionCode() {
+ /** @see AppInstallMetadata.Builder#setVersionCode(long) */
+ public long getVersionCode() {
return mVersionCode;
}
@@ -104,7 +98,7 @@ public final class AppInstallMetadata {
private String mAppCertificate;
private String mInstallerName;
private String mInstallerCertificate;
- private int mVersionCode;
+ private long mVersionCode;
private boolean mIsPreInstalled;
/**
@@ -163,7 +157,7 @@ public final class AppInstallMetadata {
* @see AppInstallMetadata#getVersionCode()
*/
@NonNull
- public Builder setVersionCode(int versionCode) {
+ public Builder setVersionCode(long versionCode) {
this.mVersionCode = versionCode;
return this;
}
diff --git a/core/java/android/content/integrity/AtomicFormula.java b/core/java/android/content/integrity/AtomicFormula.java
index 574a93ff9355..4c10a8f7ad38 100644
--- a/core/java/android/content/integrity/AtomicFormula.java
+++ b/core/java/android/content/integrity/AtomicFormula.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -20,15 +20,16 @@ import static com.android.internal.util.Preconditions.checkArgument;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.Objects;
/**
@@ -38,29 +39,28 @@ import java.util.Objects;
*
* @hide
*/
-@SystemApi
@VisibleForTesting
-public abstract class AtomicFormula implements Formula {
-
- private static final String TAG = "AtomicFormula";
+public abstract class AtomicFormula extends IntegrityFormula {
/** @hide */
@IntDef(
value = {
- PACKAGE_NAME,
- APP_CERTIFICATE,
- INSTALLER_NAME,
- INSTALLER_CERTIFICATE,
- VERSION_CODE,
- PRE_INSTALLED,
+ PACKAGE_NAME,
+ APP_CERTIFICATE,
+ INSTALLER_NAME,
+ INSTALLER_CERTIFICATE,
+ VERSION_CODE,
+ PRE_INSTALLED,
})
@Retention(RetentionPolicy.SOURCE)
- public @interface Key {}
+ public @interface Key {
+ }
/** @hide */
- @IntDef(value = {EQ, LT, LE, GT, GE})
+ @IntDef(value = {EQ, GT, GTE})
@Retention(RetentionPolicy.SOURCE)
- public @interface Operator {}
+ public @interface Operator {
+ }
/**
* Package name of the app.
@@ -94,7 +94,7 @@ public abstract class AtomicFormula implements Formula {
/**
* Version code of the app.
*
- * <p>Can only be used in {@link IntAtomicFormula}.
+ * <p>Can only be used in {@link LongAtomicFormula}.
*/
public static final int VERSION_CODE = 4;
@@ -106,10 +106,8 @@ public abstract class AtomicFormula implements Formula {
public static final int PRE_INSTALLED = 5;
public static final int EQ = 0;
- public static final int LT = 1;
- public static final int LE = 2;
- public static final int GT = 3;
- public static final int GE = 4;
+ public static final int GT = 1;
+ public static final int GTE = 2;
private final @Key int mKey;
@@ -118,78 +116,99 @@ public abstract class AtomicFormula implements Formula {
mKey = key;
}
- /** An {@link AtomicFormula} with an key and int value. */
- public static final class IntAtomicFormula extends AtomicFormula implements Parcelable {
- private final int mValue;
- private final @Operator int mOperator;
+ /** An {@link AtomicFormula} with an key and long value. */
+ public static final class LongAtomicFormula extends AtomicFormula implements Parcelable {
+ private final Long mValue;
+ private final @Operator Integer mOperator;
+
+ /**
+ * Constructs an empty {@link LongAtomicFormula}. This should only be used as a base.
+ *
+ * <p>This formula will always return false.
+ *
+ * @throws IllegalArgumentException if {@code key} cannot be used with long value
+ */
+ public LongAtomicFormula(@Key int key) {
+ super(key);
+ checkArgument(
+ key == VERSION_CODE,
+ String.format(
+ "Key %s cannot be used with LongAtomicFormula", keyToString(key)));
+ mValue = null;
+ mOperator = null;
+ }
/**
- * Constructs a new {@link IntAtomicFormula}.
+ * Constructs a new {@link LongAtomicFormula}.
*
* <p>This formula will hold if and only if the corresponding information of an install
* specified by {@code key} is of the correct relationship to {@code value} as specified by
* {@code operator}.
*
- * @throws IllegalArgumentException if {@code key} cannot be used with integer value
+ * @throws IllegalArgumentException if {@code key} cannot be used with long value
*/
- public IntAtomicFormula(@Key int key, @Operator int operator, int value) {
+ public LongAtomicFormula(@Key int key, @Operator int operator, long value) {
super(key);
checkArgument(
key == VERSION_CODE,
- String.format("Key %s cannot be used with IntAtomicFormula", keyToString(key)));
- checkArgument(isValidOperator(operator),
- String.format("Unknown operator: %d", operator));
+ String.format(
+ "Key %s cannot be used with LongAtomicFormula", keyToString(key)));
+ checkArgument(
+ isValidOperator(operator), String.format("Unknown operator: %d", operator));
mOperator = operator;
mValue = value;
}
- IntAtomicFormula(Parcel in) {
+ LongAtomicFormula(Parcel in) {
super(in.readInt());
- mValue = in.readInt();
+ mValue = in.readLong();
mOperator = in.readInt();
}
@NonNull
- public static final Creator<IntAtomicFormula> CREATOR =
- new Creator<IntAtomicFormula>() {
+ public static final Creator<LongAtomicFormula> CREATOR =
+ new Creator<LongAtomicFormula>() {
@Override
- public IntAtomicFormula createFromParcel(Parcel in) {
- return new IntAtomicFormula(in);
+ public LongAtomicFormula createFromParcel(Parcel in) {
+ return new LongAtomicFormula(in);
}
@Override
- public IntAtomicFormula[] newArray(int size) {
- return new IntAtomicFormula[size];
+ public LongAtomicFormula[] newArray(int size) {
+ return new LongAtomicFormula[size];
}
};
@Override
- public boolean isSatisfied(@NonNull AppInstallMetadata appInstallMetadata) {
- int metadataValue = getMetadataValueByKey(appInstallMetadata);
+ public int getTag() {
+ return IntegrityFormula.LONG_ATOMIC_FORMULA_TAG;
+ }
+
+ @Override
+ public boolean matches(AppInstallMetadata appInstallMetadata) {
+ if (mValue == null || mOperator == null) {
+ return false;
+ }
+
+ long metadataValue = getLongMetadataValue(appInstallMetadata, getKey());
switch (mOperator) {
case EQ:
return metadataValue == mValue;
- case LE:
- return metadataValue <= mValue;
- case LT:
- return metadataValue < mValue;
- case GE:
- return metadataValue >= mValue;
case GT:
return metadataValue > mValue;
+ case GTE:
+ return metadataValue >= mValue;
default:
- Slog.i(TAG, String.format("Unexpected operator %d", mOperator));
- return false;
+ throw new IllegalArgumentException(
+ String.format("Unexpected operator %d", mOperator));
}
}
@Override
- public int getTag() {
- return Formula.INT_ATOMIC_FORMULA_TAG;
- }
-
- @Override
public String toString() {
+ if (mValue == null || mOperator == null) {
+ return String.format("(%s)", keyToString(getKey()));
+ }
return String.format(
"(%s %s %s)", keyToString(getKey()), operatorToString(mOperator), mValue);
}
@@ -202,7 +221,7 @@ public abstract class AtomicFormula implements Formula {
if (o == null || getClass() != o.getClass()) {
return false;
}
- IntAtomicFormula that = (IntAtomicFormula) o;
+ LongAtomicFormula that = (LongAtomicFormula) o;
return getKey() == that.getKey()
&& mValue == that.mValue
&& mOperator == that.mOperator;
@@ -220,35 +239,35 @@ public abstract class AtomicFormula implements Formula {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
+ if (mValue == null || mOperator == null) {
+ throw new IllegalStateException("Cannot write an empty LongAtomicFormula.");
+ }
dest.writeInt(getKey());
- dest.writeInt(mValue);
+ dest.writeLong(mValue);
dest.writeInt(mOperator);
}
- public int getValue() {
+ public Long getValue() {
return mValue;
}
- public int getOperator() {
+ public Integer getOperator() {
return mOperator;
}
- private int getMetadataValueByKey(AppInstallMetadata appInstallMetadata) {
- switch (getKey()) {
- case VERSION_CODE:
- return appInstallMetadata.getVersionCode();
- default:
- throw new IllegalStateException(
- "Unexpected key in IntAtomicFormula" + getKey());
- }
- }
-
private static boolean isValidOperator(int operator) {
return operator == EQ
- || operator == LT
- || operator == LE
|| operator == GT
- || operator == GE;
+ || operator == GTE;
+ }
+
+ private static long getLongMetadataValue(AppInstallMetadata appInstallMetadata, int key) {
+ switch (key) {
+ case AtomicFormula.VERSION_CODE:
+ return appInstallMetadata.getVersionCode();
+ default:
+ throw new IllegalStateException("Unexpected key in IntAtomicFormula" + key);
+ }
}
}
@@ -256,7 +275,27 @@ public abstract class AtomicFormula implements Formula {
public static final class StringAtomicFormula extends AtomicFormula implements Parcelable {
private final String mValue;
// Indicates whether the value is the actual value or the hashed value.
- private final boolean mIsHashedValue;
+ private final Boolean mIsHashedValue;
+
+ /**
+ * Constructs an empty {@link StringAtomicFormula}. This should only be used as a base.
+ *
+ * <p>An empty formula will always match to false.
+ *
+ * @throws IllegalArgumentException if {@code key} cannot be used with string value
+ */
+ public StringAtomicFormula(@Key int key) {
+ super(key);
+ checkArgument(
+ key == PACKAGE_NAME
+ || key == APP_CERTIFICATE
+ || key == INSTALLER_CERTIFICATE
+ || key == INSTALLER_NAME,
+ String.format(
+ "Key %s cannot be used with StringAtomicFormula", keyToString(key)));
+ mValue = null;
+ mIsHashedValue = null;
+ }
/**
* Constructs a new {@link StringAtomicFormula}.
@@ -266,9 +305,8 @@ public abstract class AtomicFormula implements Formula {
*
* @throws IllegalArgumentException if {@code key} cannot be used with string value
*/
- public StringAtomicFormula(@Key int key, @NonNull String value, boolean isHashedValue) {
+ public StringAtomicFormula(@Key int key, @NonNull String value, boolean isHashed) {
super(key);
- mIsHashedValue = isHashedValue;
checkArgument(
key == PACKAGE_NAME
|| key == APP_CERTIFICATE
@@ -277,6 +315,30 @@ public abstract class AtomicFormula implements Formula {
String.format(
"Key %s cannot be used with StringAtomicFormula", keyToString(key)));
mValue = value;
+ mIsHashedValue = isHashed;
+ }
+
+ /**
+ * Constructs a new {@link StringAtomicFormula} together with handling the necessary
+ * hashing for the given key.
+ *
+ * <p> The value will be hashed with SHA256 and the hex digest will be computed; for
+ * all cases except when the key is PACKAGE_NAME or INSTALLER_NAME and the value
+ * is less than 33 characters.
+ *
+ * @throws IllegalArgumentException if {@code key} cannot be used with string value.
+ */
+ public StringAtomicFormula(@Key int key, @NonNull String value) {
+ super(key);
+ checkArgument(
+ key == PACKAGE_NAME
+ || key == APP_CERTIFICATE
+ || key == INSTALLER_CERTIFICATE
+ || key == INSTALLER_NAME,
+ String.format(
+ "Key %s cannot be used with StringAtomicFormula", keyToString(key)));
+ mValue = hashValue(key, value);
+ mIsHashedValue = !mValue.equals(value);
}
StringAtomicFormula(Parcel in) {
@@ -300,18 +362,23 @@ public abstract class AtomicFormula implements Formula {
};
@Override
- public boolean isSatisfied(@NonNull AppInstallMetadata appInstallMetadata) {
- String metadataValue = getMetadataValueByKey(appInstallMetadata);
- return metadataValue.equals(mValue);
+ public int getTag() {
+ return IntegrityFormula.STRING_ATOMIC_FORMULA_TAG;
}
@Override
- public int getTag() {
- return Formula.STRING_ATOMIC_FORMULA_TAG;
+ public boolean matches(AppInstallMetadata appInstallMetadata) {
+ if (mValue == null || mIsHashedValue == null) {
+ return false;
+ }
+ return getStringMetadataValue(appInstallMetadata, getKey()).equals(mValue);
}
@Override
public String toString() {
+ if (mValue == null || mIsHashedValue == null) {
+ return String.format("(%s)", keyToString(getKey()));
+ }
return String.format("(%s %s %s)", keyToString(getKey()), operatorToString(EQ), mValue);
}
@@ -339,40 +406,80 @@ public abstract class AtomicFormula implements Formula {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
+ if (mValue == null || mIsHashedValue == null) {
+ throw new IllegalStateException("Cannot write an empty StringAtomicFormula.");
+ }
dest.writeInt(getKey());
dest.writeStringNoHelper(mValue);
dest.writeByte((byte) (mIsHashedValue ? 1 : 0));
}
- @NonNull
public String getValue() {
return mValue;
}
- public boolean getIsHashedValue() {
+ public Boolean getIsHashedValue() {
return mIsHashedValue;
}
- private String getMetadataValueByKey(AppInstallMetadata appInstallMetadata) {
- switch (getKey()) {
- case PACKAGE_NAME:
+ private static String getStringMetadataValue(
+ AppInstallMetadata appInstallMetadata, int key) {
+ switch (key) {
+ case AtomicFormula.PACKAGE_NAME:
return appInstallMetadata.getPackageName();
- case APP_CERTIFICATE:
+ case AtomicFormula.APP_CERTIFICATE:
return appInstallMetadata.getAppCertificate();
- case INSTALLER_CERTIFICATE:
+ case AtomicFormula.INSTALLER_CERTIFICATE:
return appInstallMetadata.getInstallerCertificate();
- case INSTALLER_NAME:
+ case AtomicFormula.INSTALLER_NAME:
return appInstallMetadata.getInstallerName();
default:
throw new IllegalStateException(
- "Unexpected key in StringAtomicFormula: " + getKey());
+ "Unexpected key in StringAtomicFormula: " + key);
+ }
+ }
+
+ private static String hashValue(@Key int key, String value) {
+ // Hash the string value unless it is a PACKAGE_NAME or INSTALLER_NAME and the value is
+ // less than 33 characters.
+ if (value.length() <= 32) {
+ if (key == PACKAGE_NAME || key == INSTALLER_NAME) {
+ return value;
+ }
+ }
+ return hash(value);
+ }
+
+ private static String hash(String value) {
+ try {
+ MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
+ byte[] hashBytes = messageDigest.digest(value.getBytes(StandardCharsets.UTF_8));
+ return IntegrityUtils.getHexDigest(hashBytes);
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("SHA-256 algorithm not found", e);
}
}
}
/** An {@link AtomicFormula} with a key and boolean value. */
public static final class BooleanAtomicFormula extends AtomicFormula implements Parcelable {
- private final boolean mValue;
+ private final Boolean mValue;
+
+ /**
+ * Constructs an empty {@link BooleanAtomicFormula}. This should only be used as a base.
+ *
+ * <p>An empty formula will always match to false.
+ *
+ * @throws IllegalArgumentException if {@code key} cannot be used with boolean value
+ */
+ public BooleanAtomicFormula(@Key int key) {
+ super(key);
+ checkArgument(
+ key == PRE_INSTALLED,
+ String.format(
+ "Key %s cannot be used with BooleanAtomicFormula", keyToString(key)));
+ mValue = null;
+ }
/**
* Constructs a new {@link BooleanAtomicFormula}.
@@ -411,18 +518,23 @@ public abstract class AtomicFormula implements Formula {
};
@Override
- public boolean isSatisfied(@NonNull AppInstallMetadata appInstallMetadata) {
- boolean metadataValue = getMetadataValueByKey(appInstallMetadata);
- return metadataValue == mValue;
+ public int getTag() {
+ return IntegrityFormula.BOOLEAN_ATOMIC_FORMULA_TAG;
}
@Override
- public int getTag() {
- return Formula.BOOLEAN_ATOMIC_FORMULA_TAG;
+ public boolean matches(AppInstallMetadata appInstallMetadata) {
+ if (mValue == null) {
+ return false;
+ }
+ return getBooleanMetadataValue(appInstallMetadata, getKey()) == mValue;
}
@Override
public String toString() {
+ if (mValue == null) {
+ return String.format("(%s)", keyToString(getKey()));
+ }
return String.format("(%s %s %s)", keyToString(getKey()), operatorToString(EQ), mValue);
}
@@ -450,21 +562,25 @@ public abstract class AtomicFormula implements Formula {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
+ if (mValue == null) {
+ throw new IllegalStateException("Cannot write an empty BooleanAtomicFormula.");
+ }
dest.writeInt(getKey());
dest.writeByte((byte) (mValue ? 1 : 0));
}
- public boolean getValue() {
+ public Boolean getValue() {
return mValue;
}
- private boolean getMetadataValueByKey(AppInstallMetadata appInstallMetadata) {
- switch (getKey()) {
- case PRE_INSTALLED:
+ private static boolean getBooleanMetadataValue(
+ AppInstallMetadata appInstallMetadata, int key) {
+ switch (key) {
+ case AtomicFormula.PRE_INSTALLED:
return appInstallMetadata.isPreInstalled();
default:
throw new IllegalStateException(
- "Unexpected key in BooleanAtomicFormula: " + getKey());
+ "Unexpected key in BooleanAtomicFormula: " + key);
}
}
}
@@ -496,14 +612,10 @@ public abstract class AtomicFormula implements Formula {
switch (op) {
case EQ:
return "EQ";
- case LT:
- return "LT";
- case LE:
- return "LE";
case GT:
return "GT";
- case GE:
- return "GE";
+ case GTE:
+ return "GTE";
default:
throw new IllegalArgumentException("Unknown operator " + op);
}
diff --git a/core/java/android/content/integrity/CompoundFormula.java b/core/java/android/content/integrity/CompoundFormula.java
index 2a651d9e90d8..56061df21388 100644
--- a/core/java/android/content/integrity/CompoundFormula.java
+++ b/core/java/android/content/integrity/CompoundFormula.java
@@ -20,10 +20,8 @@ import static com.android.internal.util.Preconditions.checkArgument;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
@@ -42,16 +40,11 @@ import java.util.Objects;
*
* @hide
*/
-@SystemApi
@VisibleForTesting
-public final class CompoundFormula implements Formula, Parcelable {
- private static final String TAG = "OpenFormula";
+public final class CompoundFormula extends IntegrityFormula implements Parcelable {
/** @hide */
- @IntDef(
- value = {
- AND, OR, NOT,
- })
+ @IntDef(value = {AND, OR, NOT})
@Retention(RetentionPolicy.SOURCE)
public @interface Connector {}
@@ -65,7 +58,7 @@ public final class CompoundFormula implements Formula, Parcelable {
public static final int NOT = 2;
private final @Connector int mConnector;
- private final @NonNull List<Formula> mFormulas;
+ private final @NonNull List<IntegrityFormula> mFormulas;
@NonNull
public static final Creator<CompoundFormula> CREATOR =
@@ -85,9 +78,10 @@ public final class CompoundFormula implements Formula, Parcelable {
* Create a new formula from operator and operands.
*
* @throws IllegalArgumentException if the number of operands is not matching the requirements
- * for that operator (at least 2 for {@link #AND} and {@link #OR}, 1 for {@link #NOT}).
+ * for that operator (at least 2 for {@link #AND} and {@link
+ * #OR}, 1 for {@link #NOT}).
*/
- public CompoundFormula(@Connector int connector, @NonNull List<Formula> formulas) {
+ public CompoundFormula(@Connector int connector, List<IntegrityFormula> formulas) {
checkArgument(
isValidConnector(connector), String.format("Unknown connector: %d", connector));
validateFormulas(connector, formulas);
@@ -101,7 +95,7 @@ public final class CompoundFormula implements Formula, Parcelable {
checkArgument(length >= 0, "Must have non-negative length. Got " + length);
mFormulas = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
- mFormulas.add(Formula.readFromParcel(in));
+ mFormulas.add(IntegrityFormula.readFromParcel(in));
}
validateFormulas(mConnector, mFormulas);
}
@@ -111,33 +105,32 @@ public final class CompoundFormula implements Formula, Parcelable {
}
@NonNull
- public List<Formula> getFormulas() {
+ public List<IntegrityFormula> getFormulas() {
return mFormulas;
}
@Override
- public boolean isSatisfied(@NonNull AppInstallMetadata appInstallMetadata) {
- switch (mConnector) {
+ public int getTag() {
+ return IntegrityFormula.COMPOUND_FORMULA_TAG;
+ }
+
+ @Override
+ public boolean matches(AppInstallMetadata appInstallMetadata) {
+ switch (getConnector()) {
case NOT:
- return !mFormulas.get(0).isSatisfied(appInstallMetadata);
+ return !getFormulas().get(0).matches(appInstallMetadata);
case AND:
- return mFormulas.stream()
- .allMatch(formula -> formula.isSatisfied(appInstallMetadata));
+ return getFormulas().stream()
+ .allMatch(formula -> formula.matches(appInstallMetadata));
case OR:
- return mFormulas.stream()
- .anyMatch(formula -> formula.isSatisfied(appInstallMetadata));
+ return getFormulas().stream()
+ .anyMatch(formula -> formula.matches(appInstallMetadata));
default:
- Slog.i(TAG, "Unknown connector " + mConnector);
- return false;
+ throw new IllegalArgumentException("Unknown connector " + getConnector());
}
}
@Override
- public int getTag() {
- return Formula.COMPOUND_FORMULA_TAG;
- }
-
- @Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (mFormulas.size() == 1) {
@@ -180,12 +173,13 @@ public final class CompoundFormula implements Formula, Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mConnector);
dest.writeInt(mFormulas.size());
- for (Formula formula : mFormulas) {
- Formula.writeToParcel(formula, dest, flags);
+ for (IntegrityFormula formula : mFormulas) {
+ IntegrityFormula.writeToParcel(formula, dest, flags);
}
}
- private static void validateFormulas(@Connector int connector, List<Formula> formulas) {
+ private static void validateFormulas(
+ @Connector int connector, List<IntegrityFormula> formulas) {
switch (connector) {
case AND:
case OR:
diff --git a/core/java/android/content/integrity/Formula.java b/core/java/android/content/integrity/Formula.java
deleted file mode 100644
index b092a22c0191..000000000000
--- a/core/java/android/content/integrity/Formula.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.integrity;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.content.integrity.AtomicFormula.BooleanAtomicFormula;
-import android.content.integrity.AtomicFormula.IntAtomicFormula;
-import android.content.integrity.AtomicFormula.StringAtomicFormula;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Represents a rule logic/content.
- *
- * @hide
- */
-@SystemApi
-@VisibleForTesting
-public interface Formula {
- /** @hide */
- @IntDef(
- value = {
- COMPOUND_FORMULA_TAG,
- STRING_ATOMIC_FORMULA_TAG,
- INT_ATOMIC_FORMULA_TAG,
- BOOLEAN_ATOMIC_FORMULA_TAG
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Tag {}
-
- int COMPOUND_FORMULA_TAG = 0;
- int STRING_ATOMIC_FORMULA_TAG = 1;
- int INT_ATOMIC_FORMULA_TAG = 2;
- int BOOLEAN_ATOMIC_FORMULA_TAG = 3;
-
- /**
- * Returns if this formula can be satisfied by substituting the corresponding information of
- * {@code appInstallMetadata} into the formula.
- */
- boolean isSatisfied(@NonNull AppInstallMetadata appInstallMetadata);
-
- /** Returns the tag that identifies the current class. */
- @Tag int getTag();
-
- /**
- * Write a {@link Formula} to {@link android.os.Parcel}.
- *
- * <p>This helper method is needed because non-final class/interface are not allowed to be
- * {@link Parcelable}.
- *
- * @throws IllegalArgumentException if {@link Formula} is not a recognized subclass
- */
- static void writeToParcel(@NonNull Formula formula, @NonNull Parcel dest, int flags) {
- dest.writeInt(formula.getTag());
- ((Parcelable) formula).writeToParcel(dest, flags);
- }
-
- /**
- * Read a {@link Formula} from a {@link android.os.Parcel}.
- *
- * <p>We need this (hacky) helper method because non-final class/interface cannot be {@link
- * Parcelable} (api lint error).
- *
- * @throws IllegalArgumentException if the parcel cannot be parsed
- */
- @NonNull
- static Formula readFromParcel(@NonNull Parcel in) {
- int tag = in.readInt();
- switch (tag) {
- case COMPOUND_FORMULA_TAG:
- return CompoundFormula.CREATOR.createFromParcel(in);
- case STRING_ATOMIC_FORMULA_TAG:
- return StringAtomicFormula.CREATOR.createFromParcel(in);
- case INT_ATOMIC_FORMULA_TAG:
- return IntAtomicFormula.CREATOR.createFromParcel(in);
- case BOOLEAN_ATOMIC_FORMULA_TAG:
- return BooleanAtomicFormula.CREATOR.createFromParcel(in);
- default:
- throw new IllegalArgumentException("Unknown formula tag " + tag);
- }
- }
-}
diff --git a/core/java/android/content/integrity/IntegrityFormula.java b/core/java/android/content/integrity/IntegrityFormula.java
new file mode 100644
index 000000000000..0660f93e9f01
--- /dev/null
+++ b/core/java/android/content/integrity/IntegrityFormula.java
@@ -0,0 +1,277 @@
+/*
+ * 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.content.integrity;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.content.integrity.AtomicFormula.BooleanAtomicFormula;
+import android.content.integrity.AtomicFormula.LongAtomicFormula;
+import android.content.integrity.AtomicFormula.StringAtomicFormula;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+
+/**
+ * Represents a rule logic/content.
+ *
+ * @hide
+ */
+@SystemApi
+@VisibleForTesting
+public abstract class IntegrityFormula {
+
+ /**
+ * A static formula base for package name formulas.
+ *
+ * This formulation is incomplete and should always be used with {@code equals} formulation.
+ * Evaluates to false when used directly and cannot be written as a parcel.
+ */
+ @NonNull
+ public static final IntegrityFormula PACKAGE_NAME =
+ new StringAtomicFormula(AtomicFormula.PACKAGE_NAME);
+
+ /**
+ * A static formula base for app certificate formulas.
+ *
+ * This formulation is incomplete and should always be used with {@code equals} formulation.
+ * Evaluates to false when used directly and cannot be written as a parcel.
+ */
+ @NonNull
+ public static final IntegrityFormula APP_CERTIFICATE =
+ new StringAtomicFormula(AtomicFormula.APP_CERTIFICATE);
+
+ /**
+ * A static formula base for installer name formulas.
+ *
+ * This formulation is incomplete and should always be used with {@code equals} formulation.
+ * Evaluates to false when used directly and cannot be written as a parcel.
+ */
+ @NonNull
+ public static final IntegrityFormula INSTALLER_NAME =
+ new StringAtomicFormula(AtomicFormula.INSTALLER_NAME);
+
+ /**
+ * A static formula base for installer certificate formulas.
+ *
+ * This formulation is incomplete and should always be used with {@code equals} formulation.
+ * Evaluates to false when used directly and cannot be written as a parcel.
+ */
+ @NonNull
+ public static final IntegrityFormula INSTALLER_CERTIFICATE =
+ new StringAtomicFormula(AtomicFormula.INSTALLER_CERTIFICATE);
+
+ /**
+ * A static formula base for version code name formulas.
+ *
+ * This formulation is incomplete and should always be used with {@code equals},
+ * {@code greaterThan} and {@code greaterThanEquals} formulation. Evaluates to false when used
+ * directly and cannot be written as a parcel.
+ */
+ @NonNull
+ public static final IntegrityFormula VERSION_CODE =
+ new LongAtomicFormula(AtomicFormula.VERSION_CODE);
+
+ /**
+ * A static formula base for pre-installed status formulas.
+ *
+ * This formulation is incomplete and should always be used with {@code equals} formulation.
+ * Evaluates to false when used directly and cannot be written as a parcel.
+ */
+ @NonNull
+ public static final IntegrityFormula PRE_INSTALLED =
+ new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED);
+
+ /** @hide */
+ @IntDef(
+ value = {
+ COMPOUND_FORMULA_TAG,
+ STRING_ATOMIC_FORMULA_TAG,
+ LONG_ATOMIC_FORMULA_TAG,
+ BOOLEAN_ATOMIC_FORMULA_TAG
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface Tag {}
+
+ /** @hide */
+ public static final int COMPOUND_FORMULA_TAG = 0;
+ /** @hide */
+ public static final int STRING_ATOMIC_FORMULA_TAG = 1;
+ /** @hide */
+ public static final int LONG_ATOMIC_FORMULA_TAG = 2;
+ /** @hide */
+ public static final int BOOLEAN_ATOMIC_FORMULA_TAG = 3;
+
+ /**
+ * Returns the tag that identifies the current class.
+ *
+ * @hide
+ */
+ public abstract @Tag int getTag();
+
+ /**
+ * Returns true when the integrity formula is satisfied by the {@code appInstallMetadata}.
+ *
+ * @hide
+ */
+ public abstract @Tag boolean matches(AppInstallMetadata appInstallMetadata);
+
+ /**
+ * Write an {@link IntegrityFormula} to {@link android.os.Parcel}.
+ *
+ * <p>This helper method is needed because non-final class/interface are not allowed to be
+ * {@link Parcelable}.
+ *
+ * @throws IllegalArgumentException if {@link IntegrityFormula} is not a recognized subclass
+ *
+ * @hide
+ */
+ public static void writeToParcel(
+ @NonNull IntegrityFormula formula, @NonNull Parcel dest, int flags) {
+ dest.writeInt(formula.getTag());
+ ((Parcelable) formula).writeToParcel(dest, flags);
+ }
+
+ /**
+ * Read a {@link IntegrityFormula} from a {@link android.os.Parcel}.
+ *
+ * <p>We need this (hacky) helper method because non-final class/interface cannot be {@link
+ * Parcelable} (api lint error).
+ *
+ * @throws IllegalArgumentException if the parcel cannot be parsed
+ * @hide
+ */
+ @NonNull
+ public static IntegrityFormula readFromParcel(@NonNull Parcel in) {
+ int tag = in.readInt();
+ switch (tag) {
+ case COMPOUND_FORMULA_TAG:
+ return CompoundFormula.CREATOR.createFromParcel(in);
+ case STRING_ATOMIC_FORMULA_TAG:
+ return StringAtomicFormula.CREATOR.createFromParcel(in);
+ case LONG_ATOMIC_FORMULA_TAG:
+ return LongAtomicFormula.CREATOR.createFromParcel(in);
+ case BOOLEAN_ATOMIC_FORMULA_TAG:
+ return BooleanAtomicFormula.CREATOR.createFromParcel(in);
+ default:
+ throw new IllegalArgumentException("Unknown formula tag " + tag);
+ }
+ }
+
+ /**
+ * Returns an integrity formula that evaluates to true when value of the key matches to the
+ * provided string value.
+ *
+ * <p>The value will be hashed with SHA256 and the hex digest will be computed; for
+ * all cases except when the key is PACKAGE_NAME or INSTALLER_NAME and the value is less than
+ * 32 characters.
+ *
+ * <p>Throws an {@link IllegalArgumentException} if the key is not string typed.
+ */
+ @NonNull
+ public IntegrityFormula equalTo(@NonNull String value) {
+ AtomicFormula baseFormula = (AtomicFormula) this;
+ return new AtomicFormula.StringAtomicFormula(baseFormula.getKey(), value);
+ }
+
+ /**
+ * Returns an integrity formula that evaluates to true when the boolean value of the key matches
+ * the provided boolean value. It can only be used with the boolean comparison keys.
+ *
+ * <p>Throws an {@link IllegalArgumentException} if the key is not boolean typed.
+ */
+ @NonNull
+ public IntegrityFormula equalTo(boolean value) {
+ AtomicFormula baseFormula = (AtomicFormula) this;
+ return new AtomicFormula.BooleanAtomicFormula(baseFormula.getKey(), value);
+ }
+
+ /**
+ * Returns a formula that evaluates to true when the value of the key in the package being
+ * installed is equal to {@code value}.
+ *
+ * <p>Throws an {@link IllegalArgumentException} if the key is not long typed.
+ */
+ @NonNull
+ public IntegrityFormula equalTo(long value) {
+ AtomicFormula baseFormula = (AtomicFormula) this;
+ return new AtomicFormula.LongAtomicFormula(baseFormula.getKey(), AtomicFormula.EQ, value);
+ }
+
+ /**
+ * Returns a formula that evaluates to true when the value of the key in the package being
+ * installed is greater than {@code value}.
+ *
+ * <p>Throws an {@link IllegalArgumentException} if the key is not long typed.
+ */
+ @NonNull
+ public IntegrityFormula greaterThan(long value) {
+ AtomicFormula baseFormula = (AtomicFormula) this;
+ return new AtomicFormula.LongAtomicFormula(baseFormula.getKey(), AtomicFormula.GT, value);
+ }
+
+ /**
+ * Returns a formula that evaluates to true when the value of the key in the package being
+ * installed is greater than or equals to the {@code value}.
+ *
+ * <p>Throws an {@link IllegalArgumentException} if the key is not long typed.
+ */
+ @NonNull
+ public IntegrityFormula greaterThanOrEquals(long value) {
+ AtomicFormula baseFormula = (AtomicFormula) this;
+ return new AtomicFormula.LongAtomicFormula(baseFormula.getKey(), AtomicFormula.GTE, value);
+ }
+
+ /**
+ * Returns a formula that evaluates to true when any formula in {@code formulae} evaluates to
+ * true.
+ *
+ * <p>Throws an {@link IllegalArgumentException} if formulae has less than two elements.
+ */
+ @NonNull
+ public static IntegrityFormula any(@NonNull IntegrityFormula... formulae) {
+ return new CompoundFormula(CompoundFormula.OR, Arrays.asList(formulae));
+ }
+
+ /**
+ * Returns a formula that evaluates to true when all formula in {@code formulae} evaluates to
+ * true.
+ *
+ * <p>Throws an {@link IllegalArgumentException} if formulae has less than two elements.
+ */
+ @NonNull
+ public static IntegrityFormula all(@NonNull IntegrityFormula... formulae) {
+ return new CompoundFormula(CompoundFormula.AND, Arrays.asList(formulae));
+ }
+
+ /**
+ * Returns a formula that evaluates to true when {@code formula} evaluates to false.
+ */
+ @NonNull
+ public static IntegrityFormula not(@NonNull IntegrityFormula formula) {
+ return new CompoundFormula(CompoundFormula.NOT, Arrays.asList(formula));
+ }
+
+ // Constructor is package private so it cannot be inherited outside of this package.
+ IntegrityFormula() {
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/IntegrityUtils.java b/core/java/android/content/integrity/IntegrityUtils.java
index f49c675dbd8d..c3f762469348 100644
--- a/services/core/java/com/android/server/integrity/IntegrityUtils.java
+++ b/core/java/android/content/integrity/IntegrityUtils.java
@@ -14,11 +14,15 @@
* limitations under the License.
*/
-package com.android.server.integrity;
+package android.content.integrity;
import static com.android.internal.util.Preconditions.checkArgument;
-/** Utils class for simple operations used in integrity module. */
+/**
+ * Utils class for simple operations used in integrity module.
+ *
+ * @hide
+ */
public class IntegrityUtils {
private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
diff --git a/core/java/android/content/integrity/Rule.java b/core/java/android/content/integrity/Rule.java
index 77587851b18c..c421c4076d16 100644
--- a/core/java/android/content/integrity/Rule.java
+++ b/core/java/android/content/integrity/Rule.java
@@ -59,17 +59,17 @@ public final class Rule implements Parcelable {
*/
public static final int FORCE_ALLOW = 1;
- private final @NonNull Formula mFormula;
+ private final @NonNull IntegrityFormula mFormula;
private final @Effect int mEffect;
- public Rule(@NonNull Formula formula, @Effect int effect) {
+ public Rule(@NonNull IntegrityFormula formula, @Effect int effect) {
checkArgument(isValidEffect(effect), String.format("Unknown effect: %d", effect));
this.mFormula = Objects.requireNonNull(formula);
this.mEffect = effect;
}
Rule(Parcel in) {
- mFormula = Formula.readFromParcel(in);
+ mFormula = IntegrityFormula.readFromParcel(in);
mEffect = in.readInt();
}
@@ -94,12 +94,12 @@ public final class Rule implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- Formula.writeToParcel(mFormula, dest, flags);
+ IntegrityFormula.writeToParcel(mFormula, dest, flags);
dest.writeInt(mEffect);
}
@NonNull
- public Formula getFormula() {
+ public IntegrityFormula getFormula() {
return mFormula;
}
@@ -141,7 +141,6 @@ public final class Rule implements Parcelable {
}
private static boolean isValidEffect(int effect) {
- return effect == DENY
- || effect == FORCE_ALLOW;
+ return effect == DENY || effect == FORCE_ALLOW;
}
}
diff --git a/core/java/android/content/om/OverlayManager.java b/core/java/android/content/om/OverlayManager.java
index a2f8886eb7d2..33d17763fb24 100644
--- a/core/java/android/content/om/OverlayManager.java
+++ b/core/java/android/content/om/OverlayManager.java
@@ -22,7 +22,11 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.compat.Compatibility;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
import android.content.Context;
+import android.os.Build;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -40,6 +44,10 @@ public class OverlayManager {
private final IOverlayManager mService;
private final Context mContext;
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
+ private static final long THROW_SECURITY_EXCEPTIONS = 147340954;
+
/**
* Creates a new instance.
*
@@ -69,6 +77,9 @@ public class OverlayManager {
* @param packageName the name of the overlay package to enable.
* @param user The user for which to change the overlay.
*
+ * @throws SecurityException when caller is not allowed to enable {@param packageName}
+ * @throws IllegalStateException when enabling fails otherwise
+ *
* @hide
*/
@SystemApi
@@ -77,11 +88,13 @@ public class OverlayManager {
"android.permission.INTERACT_ACROSS_USERS_FULL"
})
public void setEnabledExclusiveInCategory(@NonNull final String packageName,
- @NonNull UserHandle user) {
+ @NonNull UserHandle user) throws SecurityException, IllegalStateException {
try {
if (!mService.setEnabledExclusiveInCategory(packageName, user.getIdentifier())) {
throw new IllegalStateException("setEnabledExclusiveInCategory failed");
}
+ } catch (SecurityException e) {
+ rethrowSecurityException(e);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -97,6 +110,9 @@ public class OverlayManager {
* @param enable {@code false} if the overlay should be turned off.
* @param user The user for which to change the overlay.
*
+ * @throws SecurityException when caller is not allowed to enable/disable {@param packageName}
+ * @throws IllegalStateException when enabling/disabling fails otherwise
+ *
* @hide
*/
@SystemApi
@@ -105,15 +121,16 @@ public class OverlayManager {
"android.permission.INTERACT_ACROSS_USERS_FULL"
})
public void setEnabled(@NonNull final String packageName, final boolean enable,
- @NonNull UserHandle user) {
+ @NonNull UserHandle user) throws SecurityException, IllegalStateException {
try {
if (!mService.setEnabled(packageName, enable, user.getIdentifier())) {
throw new IllegalStateException("setEnabled failed");
}
+ } catch (SecurityException e) {
+ rethrowSecurityException(e);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
- return;
}
/**
@@ -187,4 +204,29 @@ public class OverlayManager {
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Starting on R, actor enforcement and app visibility changes introduce additional failure
+ * cases, but the SecurityException thrown with these checks is unexpected for existing
+ * consumers of the API.
+ *
+ * The only prior case it would be thrown is with a permission failure, but the calling
+ * application would be able to verify that themselves, and so they may choose to ignore
+ * catching SecurityException when calling these APIs.
+ *
+ * For R, this no longer holds true, and SecurityExceptions can be thrown for any number of
+ * reasons, none of which are exposed to the caller. So for consumers targeting below R,
+ * transform these SecurityExceptions into IllegalStateExceptions, which are a little more
+ * expected to be thrown by the setEnabled APIs.
+ *
+ * This will mask the prior permission exception if it applies, but it's assumed that apps
+ * wouldn't call the APIs without the permission on prior versions, and so it's safe to ignore.
+ */
+ private void rethrowSecurityException(SecurityException e) {
+ if (!Compatibility.isChangeEnabled(THROW_SECURITY_EXCEPTIONS)) {
+ throw new IllegalStateException(e);
+ } else {
+ throw e;
+ }
+ }
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 0e7ad5de4675..66a2b7a3ac66 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3527,6 +3527,44 @@ public abstract class PackageManager {
public static final long FILTER_APPLICATION_QUERY = 135549675L;
/** {@hide} */
+ @IntDef(prefix = {"SYSTEM_APP_STATE_"}, value = {
+ SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN,
+ SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_VISIBLE,
+ SYSTEM_APP_STATE_INSTALLED,
+ SYSTEM_APP_STATE_UNINSTALLED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SystemAppState {}
+
+ /**
+ * Constant for noting system app state as hidden before installation
+ * @hide
+ */
+ @SystemApi
+ public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN = 0;
+
+ /**
+ * Constant for noting system app state as visible before installation
+ * @hide
+ */
+ @SystemApi
+ public static final int SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_VISIBLE = 1;
+
+ /**
+ * Constant for noting system app state as installed
+ * @hide
+ */
+ @SystemApi
+ public static final int SYSTEM_APP_STATE_INSTALLED = 2;
+
+ /**
+ * Constant for noting system app state as not installed
+ * @hide
+ */
+ @SystemApi
+ public static final int SYSTEM_APP_STATE_UNINSTALLED = 3;
+
+ /** {@hide} */
public int getUserId() {
return UserHandle.myUserId();
}
@@ -6630,6 +6668,17 @@ public abstract class PackageManager {
@NonNull UserHandle userHandle);
/**
+ * Sets system app state
+ * @param packageName Package name of the app.
+ * @param state State of the app.
+ * @hide
+ */
+ @SystemApi
+ public void setSystemAppState(@NonNull String packageName, @SystemAppState int state) {
+ throw new RuntimeException("Not implemented. Must override in a subclass");
+ }
+
+ /**
* Return whether the device has been booted into safe mode.
*/
public abstract boolean isSafeMode();
diff --git a/core/java/android/content/pm/SuspendDialogInfo.java b/core/java/android/content/pm/SuspendDialogInfo.java
index 73b75df80e5b..851a08116f56 100644
--- a/core/java/android/content/pm/SuspendDialogInfo.java
+++ b/core/java/android/content/pm/SuspendDialogInfo.java
@@ -19,6 +19,7 @@ package android.content.pm;
import static android.content.res.Resources.ID_NULL;
import android.annotation.DrawableRes;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
@@ -36,20 +37,21 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Locale;
import java.util.Objects;
/**
* A container to describe the dialog to be shown when the user tries to launch a suspended
- * application.
- * The suspending app can customize the dialog's following attributes:
+ * application. The suspending app can customize the dialog's following attributes:
* <ul>
* <li>The dialog icon, by providing a resource id.
* <li>The title text, by providing a resource id.
* <li>The text of the dialog's body, by providing a resource id or a string.
- * <li>The text on the neutral button which starts the
- * {@link android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS SHOW_SUSPENDED_APP_DETAILS}
- * activity, by providing a resource id.
+ * <li>The text on the neutral button by providing a resource id.
+ * <li>The action performed on tapping the neutral button. Only {@link #BUTTON_ACTION_UNSUSPEND}
+ * and {@link #BUTTON_ACTION_MORE_DETAILS} are currently supported.
* </ul>
* System defaults are used whenever any of these are not provided, or any of the provided resource
* ids cannot be resolved at the time of displaying the dialog.
@@ -67,12 +69,47 @@ public final class SuspendDialogInfo implements Parcelable {
private static final String XML_ATTR_DIALOG_MESSAGE_RES_ID = "dialogMessageResId";
private static final String XML_ATTR_DIALOG_MESSAGE = "dialogMessage";
private static final String XML_ATTR_BUTTON_TEXT_RES_ID = "buttonTextResId";
+ private static final String XML_ATTR_BUTTON_ACTION = "buttonAction";
private final int mIconResId;
private final int mTitleResId;
private final int mDialogMessageResId;
private final String mDialogMessage;
private final int mNeutralButtonTextResId;
+ private final int mNeutralButtonAction;
+
+ /**
+ * Used with {@link Builder#setNeutralButtonAction(int)} to create a neutral button that
+ * starts the {@link android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS} activity.
+ * @see Builder#setNeutralButtonAction(int)
+ */
+ public static final int BUTTON_ACTION_MORE_DETAILS = 0;
+
+ /**
+ * Used with {@link Builder#setNeutralButtonAction(int)} to create a neutral button that
+ * unsuspends the app that the user was trying to launch and continues with the launch. The
+ * system also sends the broadcast
+ * {@link android.content.Intent#ACTION_PACKAGE_UNSUSPENDED_MANUALLY} to the suspending app
+ * when this happens.
+ * @see Builder#setNeutralButtonAction(int)
+ * @see android.content.Intent#ACTION_PACKAGE_UNSUSPENDED_MANUALLY
+ */
+ public static final int BUTTON_ACTION_UNSUSPEND = 1;
+
+ /**
+ * Button actions to specify what happens when the user taps on the neutral button.
+ * To be used with {@link Builder#setNeutralButtonAction(int)}.
+ *
+ * @hide
+ * @see Builder#setNeutralButtonAction(int)
+ */
+ @IntDef(flag = true, prefix = {"BUTTON_ACTION_"}, value = {
+ BUTTON_ACTION_MORE_DETAILS,
+ BUTTON_ACTION_UNSUSPEND
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ButtonAction {
+ }
/**
* @return the resource id of the icon to be used with the dialog
@@ -102,8 +139,8 @@ public final class SuspendDialogInfo implements Parcelable {
}
/**
- * @return the text to be shown in the dialog's body. Returns {@code null} if
- * {@link #getDialogMessageResId()} returns a valid resource id.
+ * @return the text to be shown in the dialog's body. Returns {@code null} if {@link
+ * #getDialogMessageResId()} returns a valid resource id
* @hide
*/
@Nullable
@@ -121,6 +158,15 @@ public final class SuspendDialogInfo implements Parcelable {
}
/**
+ * @return The {@link ButtonAction} that happens on tapping this button
+ * @hide
+ */
+ @ButtonAction
+ public int getNeutralButtonAction() {
+ return mNeutralButtonAction;
+ }
+
+ /**
* @hide
*/
public void saveToXml(XmlSerializer out) throws IOException {
@@ -138,6 +184,7 @@ public final class SuspendDialogInfo implements Parcelable {
if (mNeutralButtonTextResId != ID_NULL) {
XmlUtils.writeIntAttribute(out, XML_ATTR_BUTTON_TEXT_RES_ID, mNeutralButtonTextResId);
}
+ XmlUtils.writeIntAttribute(out, XML_ATTR_BUTTON_ACTION, mNeutralButtonAction);
}
/**
@@ -150,6 +197,8 @@ public final class SuspendDialogInfo implements Parcelable {
final int titleId = XmlUtils.readIntAttribute(in, XML_ATTR_TITLE_RES_ID, ID_NULL);
final int buttonTextId = XmlUtils.readIntAttribute(in, XML_ATTR_BUTTON_TEXT_RES_ID,
ID_NULL);
+ final int buttonAction = XmlUtils.readIntAttribute(in, XML_ATTR_BUTTON_ACTION,
+ BUTTON_ACTION_MORE_DETAILS);
final int dialogMessageResId = XmlUtils.readIntAttribute(
in, XML_ATTR_DIALOG_MESSAGE_RES_ID, ID_NULL);
final String dialogMessage = XmlUtils.readStringAttribute(in, XML_ATTR_DIALOG_MESSAGE);
@@ -168,6 +217,7 @@ public final class SuspendDialogInfo implements Parcelable {
} else if (dialogMessage != null) {
dialogInfoBuilder.setMessage(dialogMessage);
}
+ dialogInfoBuilder.setNeutralButtonAction(buttonAction);
} catch (Exception e) {
Slog.e(TAG, "Exception while parsing from xml. Some fields may default", e);
}
@@ -181,6 +231,7 @@ public final class SuspendDialogInfo implements Parcelable {
hashCode = 31 * hashCode + mNeutralButtonTextResId;
hashCode = 31 * hashCode + mDialogMessageResId;
hashCode = 31 * hashCode + Objects.hashCode(mDialogMessage);
+ hashCode = 31 * hashCode + mNeutralButtonAction;
return hashCode;
}
@@ -197,6 +248,7 @@ public final class SuspendDialogInfo implements Parcelable {
&& mTitleResId == otherDialogInfo.mTitleResId
&& mDialogMessageResId == otherDialogInfo.mDialogMessageResId
&& mNeutralButtonTextResId == otherDialogInfo.mNeutralButtonTextResId
+ && mNeutralButtonAction == otherDialogInfo.mNeutralButtonAction
&& Objects.equals(mDialogMessage, otherDialogInfo.mDialogMessage);
}
@@ -228,6 +280,8 @@ public final class SuspendDialogInfo implements Parcelable {
builder.append(mDialogMessage);
builder.append("\" ");
}
+ builder.append("mNeutralButtonAction = ");
+ builder.append(mNeutralButtonAction);
builder.append("}");
return builder.toString();
}
@@ -244,6 +298,7 @@ public final class SuspendDialogInfo implements Parcelable {
dest.writeInt(mDialogMessageResId);
dest.writeString(mDialogMessage);
dest.writeInt(mNeutralButtonTextResId);
+ dest.writeInt(mNeutralButtonAction);
}
private SuspendDialogInfo(Parcel source) {
@@ -252,6 +307,7 @@ public final class SuspendDialogInfo implements Parcelable {
mDialogMessageResId = source.readInt();
mDialogMessage = source.readString();
mNeutralButtonTextResId = source.readInt();
+ mNeutralButtonAction = source.readInt();
}
SuspendDialogInfo(Builder b) {
@@ -260,9 +316,11 @@ public final class SuspendDialogInfo implements Parcelable {
mDialogMessageResId = b.mDialogMessageResId;
mDialogMessage = (mDialogMessageResId == ID_NULL) ? b.mDialogMessage : null;
mNeutralButtonTextResId = b.mNeutralButtonTextResId;
+ mNeutralButtonAction = b.mNeutralButtonAction;
}
- public static final @android.annotation.NonNull Creator<SuspendDialogInfo> CREATOR = new Creator<SuspendDialogInfo>() {
+ public static final @NonNull Creator<SuspendDialogInfo> CREATOR =
+ new Creator<SuspendDialogInfo>() {
@Override
public SuspendDialogInfo createFromParcel(Parcel source) {
return new SuspendDialogInfo(source);
@@ -283,6 +341,7 @@ public final class SuspendDialogInfo implements Parcelable {
private int mTitleResId = ID_NULL;
private int mIconResId = ID_NULL;
private int mNeutralButtonTextResId = ID_NULL;
+ private int mNeutralButtonAction = BUTTON_ACTION_MORE_DETAILS;
/**
* Set the resource id of the icon to be used. If not provided, no icon will be shown.
@@ -333,8 +392,8 @@ public final class SuspendDialogInfo implements Parcelable {
/**
* Set the resource id of the dialog message to be shown. If no dialog message is provided
- * via either this method or {@link #setMessage(String)}, the system will use a
- * default message.
+ * via either this method or {@link #setMessage(String)}, the system will use a default
+ * message.
* <p>
* The system will use {@link android.content.res.Resources#getString(int, Object...)
* getString} to insert the suspended app name into the message, so an example format string
@@ -353,9 +412,10 @@ public final class SuspendDialogInfo implements Parcelable {
}
/**
- * Set the resource id of text to be shown on the neutral button. Tapping this button starts
- * the {@link android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS} activity. If this is
- * not provided, the system will use a default text.
+ * Set the resource id of text to be shown on the neutral button. Tapping this button would
+ * perform the {@link ButtonAction action} specified through
+ * {@link #setNeutralButtonAction(int)}. If this is not provided, the system will use a
+ * default text.
*
* @param resId The resource id of the button text
* @return this builder object.
@@ -368,6 +428,22 @@ public final class SuspendDialogInfo implements Parcelable {
}
/**
+ * Set the action expected to happen on neutral button tap. Defaults to
+ * {@link #BUTTON_ACTION_MORE_DETAILS} if this is not provided.
+ *
+ * @param buttonAction Either {@link #BUTTON_ACTION_MORE_DETAILS} or
+ * {@link #BUTTON_ACTION_UNSUSPEND}.
+ * @return this builder object
+ */
+ @NonNull
+ public Builder setNeutralButtonAction(@ButtonAction int buttonAction) {
+ Preconditions.checkArgument(buttonAction == BUTTON_ACTION_MORE_DETAILS
+ || buttonAction == BUTTON_ACTION_UNSUSPEND, "Invalid button action");
+ mNeutralButtonAction = buttonAction;
+ return this;
+ }
+
+ /**
* Build the final object based on given inputs.
*
* @return The {@link SuspendDialogInfo} object built using this builder.
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index a71a7b63f30e..cc4c45699bd4 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -693,6 +693,22 @@ public final class Sensor {
"android.sensor.accelerometer_uncalibrated";
/**
+ * A constant describing a hinge angle sensor.
+ *
+ * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
+ *
+ */
+ public static final int TYPE_HINGE_ANGLE = 36;
+
+ /**
+ * A constant string describing a hinge angle sensor.
+ *
+ * @see #TYPE_HINGE_ANGLE
+ *
+ */
+ public static final String STRING_TYPE_HINGE_ANGLE = "android.sensor.hinge_angle";
+
+ /**
* A constant describing all sensor types.
*/
@@ -811,6 +827,7 @@ public final class Sensor {
16, // skip over additional sensor info type
1, // SENSOR_TYPE_LOW_LATENCY_OFFBODY_DETECT
6, // SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED
+ 1, // SENSOR_TYPE_HINGE_ANGLE
};
/**
@@ -1226,6 +1243,8 @@ public final class Sensor {
case TYPE_ACCELEROMETER_UNCALIBRATED:
mStringType = STRING_TYPE_ACCELEROMETER_UNCALIBRATED;
return true;
+ case TYPE_HINGE_ANGLE:
+ mStringType = STRING_TYPE_HINGE_ANGLE;
default:
return false;
}
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 64c45bf290ec..5fbf0da8b5a5 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -630,6 +630,16 @@ public class SensorEvent {
* x_bias, y_bias, z_bias are the estimated biases.
* </p>
*
+ * <h4>{@link android.hardware.Sensor#TYPE_HINGE_ANGLE Sensor.TYPE_HINGE_ANGLE}:</h4>
+ *
+ * A sensor of this type measures the angle, in degrees, between two integral parts of the
+ * device. Movement of a hinge measured by this sensor type is expected to alter the ways in
+ * which the user may interact with the device, for example by unfolding or revealing a display.
+ *
+ * <ul>
+ * <li> values[0]: Measured hinge angle between 0 and 360 degrees inclusive</li>
+ * </ul>
+ *
* @see GeomagneticField
*/
public final float[] values;
diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java
index 456481386cc9..b13e4b72aa22 100644
--- a/core/java/android/net/ConnectivityDiagnosticsManager.java
+++ b/core/java/android/net/ConnectivityDiagnosticsManager.java
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
import android.content.Context;
+import android.os.Binder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
@@ -544,6 +545,53 @@ public class ConnectivityDiagnosticsManager {
};
}
+ /** @hide */
+ @VisibleForTesting
+ public static class ConnectivityDiagnosticsBinder
+ extends IConnectivityDiagnosticsCallback.Stub {
+ @NonNull private final ConnectivityDiagnosticsCallback mCb;
+ @NonNull private final Executor mExecutor;
+
+ /** @hide */
+ @VisibleForTesting
+ public ConnectivityDiagnosticsBinder(
+ @NonNull ConnectivityDiagnosticsCallback cb, @NonNull Executor executor) {
+ this.mCb = cb;
+ this.mExecutor = executor;
+ }
+
+ /** @hide */
+ @VisibleForTesting
+ public void onConnectivityReport(@NonNull ConnectivityReport report) {
+ Binder.withCleanCallingIdentity(() -> {
+ mExecutor.execute(() -> {
+ mCb.onConnectivityReport(report);
+ });
+ });
+ }
+
+ /** @hide */
+ @VisibleForTesting
+ public void onDataStallSuspected(@NonNull DataStallReport report) {
+ Binder.withCleanCallingIdentity(() -> {
+ mExecutor.execute(() -> {
+ mCb.onDataStallSuspected(report);
+ });
+ });
+ }
+
+ /** @hide */
+ @VisibleForTesting
+ public void onNetworkConnectivityReported(
+ @NonNull Network network, boolean hasConnectivity) {
+ Binder.withCleanCallingIdentity(() -> {
+ mExecutor.execute(() -> {
+ mCb.onNetworkConnectivityReported(network, hasConnectivity);
+ });
+ });
+ }
+ }
+
/**
* Abstract base class for Connectivity Diagnostics callbacks. Used for notifications about
* network connectivity events. Must be extended by applications wanting notifications.
diff --git a/core/java/android/net/IConnectivityDiagnosticsCallback.aidl b/core/java/android/net/IConnectivityDiagnosticsCallback.aidl
new file mode 100644
index 000000000000..3a161bfabfd2
--- /dev/null
+++ b/core/java/android/net/IConnectivityDiagnosticsCallback.aidl
@@ -0,0 +1,28 @@
+/**
+ *
+ * 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.net;
+
+import android.net.ConnectivityDiagnosticsManager;
+import android.net.Network;
+
+/** @hide */
+oneway interface IConnectivityDiagnosticsCallback {
+ void onConnectivityReport(in ConnectivityDiagnosticsManager.ConnectivityReport report);
+ void onDataStallSuspected(in ConnectivityDiagnosticsManager.DataStallReport report);
+ void onNetworkConnectivityReported(in Network n, boolean hasConnectivity);
+} \ No newline at end of file
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 186196bd31c7..3e9e7faccb02 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -18,6 +18,7 @@ package android.net;
import android.app.PendingIntent;
import android.net.ConnectionInfo;
+import android.net.IConnectivityDiagnosticsCallback;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkAgentConfig;
@@ -211,5 +212,9 @@ interface IConnectivityManager
boolean isCallerCurrentAlwaysOnVpnApp();
boolean isCallerCurrentAlwaysOnVpnLockdownApp();
+ void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback,
+ in NetworkRequest request);
+ void unregisterConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback);
+
IBinder startOrGetTestNetworkService();
}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index a94109dae7d5..4f4e27b446ef 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -26,6 +26,7 @@ import android.net.ConnectivityManager.NetworkCallback;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.Process;
import android.util.ArraySet;
import android.util.proto.ProtoOutputStream;
@@ -58,7 +59,6 @@ import java.util.StringJoiner;
*/
public final class NetworkCapabilities implements Parcelable {
private static final String TAG = "NetworkCapabilities";
- private static final int INVALID_UID = -1;
// Set to true when private DNS is broken.
private boolean mPrivateDnsBroken;
@@ -85,8 +85,8 @@ public final class NetworkCapabilities implements Parcelable {
mTransportInfo = null;
mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED;
mUids = null;
- mEstablishingVpnAppUid = INVALID_UID;
mAdministratorUids.clear();
+ mOwnerUid = Process.INVALID_UID;
mSSID = null;
mPrivateDnsBroken = false;
}
@@ -104,8 +104,8 @@ public final class NetworkCapabilities implements Parcelable {
mTransportInfo = nc.mTransportInfo;
mSignalStrength = nc.mSignalStrength;
setUids(nc.mUids); // Will make the defensive copy
- mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid;
setAdministratorUids(nc.mAdministratorUids);
+ mOwnerUid = nc.mOwnerUid;
mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
mSSID = nc.mSSID;
mPrivateDnsBroken = nc.mPrivateDnsBroken;
@@ -810,31 +810,26 @@ public final class NetworkCapabilities implements Parcelable {
}
/**
- * UID of the app that manages this network, or INVALID_UID if none/unknown.
+ * UID of the app that owns this network, or INVALID_UID if none/unknown.
*
- * This field keeps track of the UID of the app that created this network and is in charge
- * of managing it. In the practice, it is used to store the UID of VPN apps so it is named
- * accordingly, but it may be renamed if other mechanisms are offered for third party apps
- * to create networks.
- *
- * Because this field is only used in the services side (and to avoid apps being able to
- * set this to whatever they want), this field is not parcelled and will not be conserved
- * across the IPC boundary.
- * @hide
+ * <p>This field keeps track of the UID of the app that created this network and is in charge of
+ * its lifecycle. This could be the UID of apps such as the Wifi network suggestor, the running
+ * VPN, or Carrier Service app managing a cellular data connection.
*/
- private int mEstablishingVpnAppUid = INVALID_UID;
+ private int mOwnerUid = Process.INVALID_UID;
/**
- * Set the UID of the managing app.
- * @hide
+ * Set the UID of the owner app.
*/
- public void setEstablishingVpnAppUid(final int uid) {
- mEstablishingVpnAppUid = uid;
+ public void setOwnerUid(final int uid) {
+ mOwnerUid = uid;
}
- /** @hide */
- public int getEstablishingVpnAppUid() {
- return mEstablishingVpnAppUid;
+ /**
+ * Retrieves the UID of the owner app.
+ */
+ public int getOwnerUid() {
+ return mOwnerUid;
}
/**
@@ -1157,7 +1152,7 @@ public final class NetworkCapabilities implements Parcelable {
* member is null, then the network is not restricted by app UID. If it's an empty list, then
* it means nobody can use it.
* As a special exception, the app managing this network (as identified by its UID stored in
- * mEstablishingVpnAppUid) can always see this network. This is embodied by a special check in
+ * mOwnerUid) can always see this network. This is embodied by a special check in
* satisfiedByUids. That still does not mean the network necessarily <strong>applies</strong>
* to the app that manages it as determined by #appliesToUid.
* <p>
@@ -1264,7 +1259,7 @@ public final class NetworkCapabilities implements Parcelable {
* in the passed nc (representing the UIDs that this network is available to).
* <p>
* As a special exception, the UID that created the passed network (as represented by its
- * mEstablishingVpnAppUid field) always satisfies a NetworkRequest requiring it (of LISTEN
+ * mOwnerUid field) always satisfies a NetworkRequest requiring it (of LISTEN
* or REQUEST types alike), even if the network does not apply to it. That is so a VPN app
* can see its own network when it listens for it.
* <p>
@@ -1275,7 +1270,7 @@ public final class NetworkCapabilities implements Parcelable {
public boolean satisfiedByUids(@NonNull NetworkCapabilities nc) {
if (null == nc.mUids || null == mUids) return true; // The network satisfies everything.
for (UidRange requiredRange : mUids) {
- if (requiredRange.contains(nc.mEstablishingVpnAppUid)) return true;
+ if (requiredRange.contains(nc.mOwnerUid)) return true;
if (!nc.appliesToUidRange(requiredRange)) {
return false;
}
@@ -1541,6 +1536,7 @@ public final class NetworkCapabilities implements Parcelable {
dest.writeString(mSSID);
dest.writeBoolean(mPrivateDnsBroken);
dest.writeList(mAdministratorUids);
+ dest.writeInt(mOwnerUid);
}
public static final @android.annotation.NonNull Creator<NetworkCapabilities> CREATOR =
@@ -1562,6 +1558,7 @@ public final class NetworkCapabilities implements Parcelable {
netCap.mSSID = in.readString();
netCap.mPrivateDnsBroken = in.readBoolean();
netCap.setAdministratorUids(in.readArrayList(null));
+ netCap.mOwnerUid = in.readInt();
return netCap;
}
@Override
@@ -1611,8 +1608,8 @@ public final class NetworkCapabilities implements Parcelable {
sb.append(" Uids: <").append(mUids).append(">");
}
}
- if (mEstablishingVpnAppUid != INVALID_UID) {
- sb.append(" EstablishingAppUid: ").append(mEstablishingVpnAppUid);
+ if (mOwnerUid != Process.INVALID_UID) {
+ sb.append(" OwnerUid: ").append(mOwnerUid);
}
if (!mAdministratorUids.isEmpty()) {
diff --git a/core/java/android/os/BatteryStatsManager.java b/core/java/android/os/BatteryStatsManager.java
index f2e16b46422f..152141edb52d 100644
--- a/core/java/android/os/BatteryStatsManager.java
+++ b/core/java/android/os/BatteryStatsManager.java
@@ -42,7 +42,7 @@ import java.lang.annotation.RetentionPolicy;
*/
@SystemApi
@SystemService(Context.BATTERY_STATS_SERVICE)
-public final class BatteryStatsManager {
+public class BatteryStatsManager {
/**
* Wifi states.
*
diff --git a/core/java/android/os/TelephonyServiceManager.java b/core/java/android/os/TelephonyServiceManager.java
index c93eba6523f0..c67dedb4ac17 100644
--- a/core/java/android/os/TelephonyServiceManager.java
+++ b/core/java/android/os/TelephonyServiceManager.java
@@ -191,14 +191,6 @@ public class TelephonyServiceManager {
}
/**
- * Returns {@link ServiceRegisterer} for the package manager service.
- */
- @NonNull
- public ServiceRegisterer getPackageManagerServiceRegisterer() {
- return new ServiceRegisterer("package");
- }
-
- /**
* Returns {@link ServiceRegisterer} for the ICC phone book service.
*/
@NonNull
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 5a1ba7fe534c..4812ea98b569 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -266,6 +266,28 @@ public final class PermissionManager {
}
}
+ /**
+ * Grant default permissions to currently enabled carrier apps
+ * @param packageNames Package names of the apps to be granted permissions
+ * @param user The user handle
+ * @param executor The executor for the callback
+ * @param callback The callback provided by caller to be notified when grant completes
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS)
+ public void grantDefaultPermissionsToEnabledCarrierApps(@NonNull String[] packageNames,
+ @NonNull UserHandle user, @NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<Boolean> callback) {
+ try {
+ mPermissionManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames,
+ user.getIdentifier());
+ executor.execute(() -> callback.accept(true));
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
private List<SplitPermissionInfo> splitPermissionInfoListToNonParcelableList(
List<SplitPermissionInfoParcelable> parcelableList) {
final int size = parcelableList.size();
@@ -416,4 +438,4 @@ public final class PermissionManager {
e.rethrowFromSystemServer();
}
}
-}
+} \ No newline at end of file
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 38768c393e18..21d99fcf8231 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9737,6 +9737,15 @@ public final class Settings {
*/
public static final String PACKAGE_VERIFIER_INCLUDE_ADB = "verifier_verify_adb_installs";
+ /**
+ * Run integrity checks for integrity rule providers.
+ * 0 = bypass integrity verification on installs from rule providers (default)
+ * 1 = perform integrity verification on installs from rule providers
+ * @hide
+ */
+ public static final String INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER =
+ "verify_integrity_for_rule_provider";
+
/**
* Time since last fstrim (milliseconds) after which we force one to happen
* during device startup. If unset, the default is 3 days.
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 4f400a8e9cb2..c5d97b718ff0 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -17,7 +17,8 @@
package android.service.notification;
import static android.app.NotificationChannel.PLACEHOLDER_CONVERSATION_ID;
-import static android.util.FeatureFlagUtils.*;
+import static android.util.FeatureFlagUtils.NOTIF_CONVO_BYPASS_SHORTCUT_REQ;
+import static android.util.FeatureFlagUtils.isEnabled;
import android.annotation.NonNull;
import android.app.Notification;
@@ -33,7 +34,6 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import android.text.TextUtils;
-import android.util.FeatureFlagUtils;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -454,11 +454,23 @@ public class StatusBarNotification implements Parcelable {
return conversationId;
}
- private String getGroupLogTag() {
+ /**
+ * Returns a probably-unique string based on the notification's group name,
+ * with no more than MAX_LOG_TAG_LENGTH characters.
+ * @return String based on group name of notification.
+ * @hide
+ */
+ public String getGroupLogTag() {
return shortenTag(getGroup());
}
- private String getChannelIdLogTag() {
+ /**
+ * Returns a probably-unique string based on the notification's channel ID,
+ * with no more than MAX_LOG_TAG_LENGTH characters.
+ * @return String based on channel ID of notification.
+ * @hide
+ */
+ public String getChannelIdLogTag() {
if (notification.getChannelId() == null) {
return null;
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index d9c502e14e68..14390f1c209b 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -748,4 +748,9 @@ interface IWindowManager
void getWindowInsets(in WindowManager.LayoutParams attrs, int displayId,
out Rect outContentInsets, out Rect outStableInsets,
out DisplayCutout.ParcelableWrapper displayCutout);
+
+ /**
+ * Called to show global actions.
+ */
+ void showGlobalActions();
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index f7b87cce7338..811b0637db98 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -2551,6 +2551,7 @@ public final class SurfaceControl implements Parcelable {
/**
* @hide
*/
+ @Deprecated
@UnsupportedAppUsage
public Transaction deferTransactionUntilSurface(SurfaceControl sc, Surface barrierSurface,
long frameNumber) {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 1981bdd93eeb..75d5538faedd 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -414,7 +414,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
}
t.setAlpha(mSurfaceControl, alpha);
if (!useBLAST) {
- t.deferTransactionUntilSurface(mSurfaceControl, parent, frame);
+ t.deferTransactionUntil(mSurfaceControl,
+ viewRoot.getRenderSurfaceControl(), frame);
}
}
// It's possible that mSurfaceControl is released in the UI thread before
@@ -1122,7 +1123,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
if (frameNumber > 0 && !WindowManagerGlobal.USE_BLAST_ADAPTER) {
final ViewRootImpl viewRoot = getViewRootImpl();
- t.deferTransactionUntilSurface(surface, viewRoot.mSurface,
+ t.deferTransactionUntil(surface, viewRoot.getRenderSurfaceControl(),
frameNumber);
}
@@ -1217,8 +1218,8 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
if (frameNumber > 0 && viewRoot != null && !useBLAST) {
if (viewRoot.mSurface.isValid()) {
- mRtTransaction.deferTransactionUntilSurface(mSurfaceControl, viewRoot.mSurface,
- frameNumber);
+ mRtTransaction.deferTransactionUntil(mSurfaceControl,
+ viewRoot.getRenderSurfaceControl(), frameNumber);
}
}
t.hide(mSurfaceControl);
diff --git a/core/java/android/view/SyncRtSurfaceTransactionApplier.java b/core/java/android/view/SyncRtSurfaceTransactionApplier.java
index a6536f5d83b7..abe44f45aba5 100644
--- a/core/java/android/view/SyncRtSurfaceTransactionApplier.java
+++ b/core/java/android/view/SyncRtSurfaceTransactionApplier.java
@@ -38,7 +38,7 @@ public class SyncRtSurfaceTransactionApplier {
public static final int FLAG_CORNER_RADIUS = 1 << 4;
public static final int FLAG_VISIBILITY = 1 << 5;
- private final Surface mTargetSurface;
+ private SurfaceControl mTargetSc;
private final ViewRootImpl mTargetViewRootImpl;
private final float[] mTmpFloat9 = new float[9];
@@ -47,7 +47,6 @@ public class SyncRtSurfaceTransactionApplier {
*/
public SyncRtSurfaceTransactionApplier(View targetView) {
mTargetViewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
- mTargetSurface = mTargetViewRootImpl != null ? mTargetViewRootImpl.mSurface : null;
}
/**
@@ -60,15 +59,16 @@ public class SyncRtSurfaceTransactionApplier {
if (mTargetViewRootImpl == null) {
return;
}
+ mTargetSc = mTargetViewRootImpl.getRenderSurfaceControl();
mTargetViewRootImpl.registerRtFrameCallback(frame -> {
- if (mTargetSurface == null || !mTargetSurface.isValid()) {
+ if (mTargetSc == null || !mTargetSc.isValid()) {
return;
}
Transaction t = new Transaction();
for (int i = params.length - 1; i >= 0; i--) {
SurfaceParams surfaceParams = params[i];
SurfaceControl surface = surfaceParams.surface;
- t.deferTransactionUntilSurface(surface, mTargetSurface, frame);
+ t.deferTransactionUntil(surface, mTargetSc, frame);
applyParams(t, surfaceParams, mTmpFloat9);
}
t.setEarlyWakeup();
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f5cfbec924ac..7a93dcc9e4ec 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1733,8 +1733,8 @@ public final class ViewRootImpl implements ViewParent,
private void updateBoundsLayer() {
if (mBoundsLayer != null) {
setBoundsLayerCrop();
- mTransaction.deferTransactionUntilSurface(mBoundsLayer,
- mSurface, mSurface.getNextFrameNumber())
+ mTransaction.deferTransactionUntil(mBoundsLayer,
+ getRenderSurfaceControl(), mSurface.getNextFrameNumber())
.apply();
}
}
@@ -9539,4 +9539,12 @@ public final class ViewRootImpl implements ViewParent,
SurfaceControl.Transaction getBLASTSyncTransaction() {
return mRtBLASTSyncTransaction;
}
+
+ SurfaceControl getRenderSurfaceControl() {
+ if (WindowManagerGlobal.USE_BLAST_ADAPTER) {
+ return mBlastSurfaceControl;
+ } else {
+ return mSurfaceControl;
+ }
+ }
}
diff --git a/core/java/com/android/internal/app/BlockedAppActivity.java b/core/java/com/android/internal/app/BlockedAppActivity.java
deleted file mode 100644
index fbdbbfb06b78..000000000000
--- a/core/java/com/android/internal/app/BlockedAppActivity.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.util.Slog;
-
-import com.android.internal.R;
-
-/**
- * A dialog shown to the user when they try to launch an app that is not allowed in lock task
- * mode. The intent to start this activity must be created with the static factory method provided
- * below.
- */
-public class BlockedAppActivity extends AlertActivity {
-
- private static final String TAG = "BlockedAppActivity";
- private static final String PACKAGE_NAME = "com.android.internal.app";
- private static final String EXTRA_BLOCKED_PACKAGE = PACKAGE_NAME + ".extra.BLOCKED_PACKAGE";
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- Intent intent = getIntent();
- int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, /* defaultValue= */ -1);
- if (userId < 0) {
- Slog.wtf(TAG, "Invalid user: " + userId);
- finish();
- return;
- }
-
- String packageName = intent.getStringExtra(EXTRA_BLOCKED_PACKAGE);
- if (TextUtils.isEmpty(packageName)) {
- Slog.wtf(TAG, "Invalid package: " + packageName);
- finish();
- return;
- }
-
- CharSequence appLabel = getAppLabel(userId, packageName);
-
- mAlertParams.mTitle = getString(R.string.app_blocked_title);
- mAlertParams.mMessage = getString(R.string.app_blocked_message, appLabel);
- mAlertParams.mPositiveButtonText = getString(android.R.string.ok);
- setupAlert();
- }
-
- private CharSequence getAppLabel(int userId, String packageName) {
- PackageManager pm = getPackageManager();
- try {
- ApplicationInfo aInfo =
- pm.getApplicationInfoAsUser(packageName, /* flags= */ 0, userId);
- return aInfo.loadLabel(pm);
- } catch (PackageManager.NameNotFoundException ne) {
- Slog.e(TAG, "Package " + packageName + " not found", ne);
- }
- return packageName;
- }
-
-
- /** Creates an intent that launches {@link BlockedAppActivity}. */
- public static Intent createIntent(int userId, String packageName) {
- return new Intent()
- .setClassName("android", BlockedAppActivity.class.getName())
- .putExtra(Intent.EXTRA_USER_ID, userId)
- .putExtra(EXTRA_BLOCKED_PACKAGE, packageName);
- }
-}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 68d6e03f654c..96ab0bb4afc4 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1101,6 +1101,9 @@ public class ResolverActivity extends Activity implements
}
if (target != null) {
+ if (intent != null) {
+ intent.fixUris(UserHandle.myUserId());
+ }
safelyStartActivity(target);
// Rely on the ActivityManager to pop up a dialog regarding app suspension
diff --git a/core/java/com/android/internal/app/SuspendedAppActivity.java b/core/java/com/android/internal/app/SuspendedAppActivity.java
index c610ac4503c9..0589baa76b8a 100644
--- a/core/java/com/android/internal/app/SuspendedAppActivity.java
+++ b/core/java/com/android/internal/app/SuspendedAppActivity.java
@@ -18,23 +18,31 @@ package com.android.internal.app;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_MORE_DETAILS;
+import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_UNSUSPEND;
import static android.content.res.Resources.ID_NULL;
import android.Manifest;
+import android.annotation.Nullable;
import android.app.AlertDialog;
+import android.app.AppGlobals;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.IntentSender;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.SuspendDialogInfo;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Slog;
import android.view.WindowManager;
import com.android.internal.R;
+import com.android.internal.util.ArrayUtils;
public class SuspendedAppActivity extends AlertActivity
implements DialogInterface.OnClickListener {
@@ -46,8 +54,13 @@ public class SuspendedAppActivity extends AlertActivity
PACKAGE_NAME + ".extra.SUSPENDING_PACKAGE";
public static final String EXTRA_DIALOG_INFO = PACKAGE_NAME + ".extra.DIALOG_INFO";
public static final String EXTRA_ACTIVITY_OPTIONS = PACKAGE_NAME + ".extra.ACTIVITY_OPTIONS";
+ public static final String EXTRA_UNSUSPEND_INTENT = PACKAGE_NAME + ".extra.UNSUSPEND_INTENT";
private Intent mMoreDetailsIntent;
+ private IntentSender mOnUnsuspend;
+ private String mSuspendedPackage;
+ private String mSuspendingPackage;
+ private int mNeutralButtonAction;
private int mUserId;
private PackageManager mPm;
private Resources mSuspendingAppResources;
@@ -63,16 +76,15 @@ public class SuspendedAppActivity extends AlertActivity
return packageName;
}
- private Intent getMoreDetailsActivity(String suspendingPackage, String suspendedPackage,
- int userId) {
+ private Intent getMoreDetailsActivity() {
final Intent moreDetailsIntent = new Intent(Intent.ACTION_SHOW_SUSPENDED_APP_DETAILS)
- .setPackage(suspendingPackage);
+ .setPackage(mSuspendingPackage);
final String requiredPermission = Manifest.permission.SEND_SHOW_SUSPENDED_APP_DETAILS;
final ResolveInfo resolvedInfo = mPm.resolveActivityAsUser(moreDetailsIntent,
- MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE, userId);
+ MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE, mUserId);
if (resolvedInfo != null && resolvedInfo.activityInfo != null
&& requiredPermission.equals(resolvedInfo.activityInfo.permission)) {
- moreDetailsIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, suspendedPackage)
+ moreDetailsIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, mSuspendedPackage)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
return moreDetailsIntent;
}
@@ -105,8 +117,8 @@ public class SuspendedAppActivity extends AlertActivity
return getString(R.string.app_suspended_title);
}
- private String resolveDialogMessage(String suspendingPkg, String suspendedPkg) {
- final CharSequence suspendedAppLabel = getAppLabel(suspendedPkg);
+ private String resolveDialogMessage() {
+ final CharSequence suspendedAppLabel = getAppLabel(mSuspendedPackage);
if (mSuppliedDialogInfo != null) {
final int messageId = mSuppliedDialogInfo.getDialogMessageResId();
final String message = mSuppliedDialogInfo.getDialogMessage();
@@ -122,10 +134,30 @@ public class SuspendedAppActivity extends AlertActivity
}
}
return getString(R.string.app_suspended_default_message, suspendedAppLabel,
- getAppLabel(suspendingPkg));
+ getAppLabel(mSuspendingPackage));
}
+ /**
+ * Returns a text to be displayed on the neutral button or {@code null} if the button should
+ * not be shown.
+ */
+ @Nullable
private String resolveNeutralButtonText() {
+ final int defaultButtonTextId;
+ switch (mNeutralButtonAction) {
+ case BUTTON_ACTION_MORE_DETAILS:
+ if (mMoreDetailsIntent == null) {
+ return null;
+ }
+ defaultButtonTextId = R.string.app_suspended_more_details;
+ break;
+ case BUTTON_ACTION_UNSUSPEND:
+ defaultButtonTextId = R.string.app_suspended_unsuspend_message;
+ break;
+ default:
+ Slog.w(TAG, "Unknown neutral button action: " + mNeutralButtonAction);
+ return null;
+ }
final int buttonTextId = (mSuppliedDialogInfo != null)
? mSuppliedDialogInfo.getNeutralButtonTextResId() : ID_NULL;
if (buttonTextId != ID_NULL && mSuspendingAppResources != null) {
@@ -135,7 +167,7 @@ public class SuspendedAppActivity extends AlertActivity
Slog.e(TAG, "Could not resolve string resource id " + buttonTextId);
}
}
- return getString(R.string.app_suspended_more_details);
+ return getString(defaultButtonTextId);
}
@Override
@@ -152,27 +184,29 @@ public class SuspendedAppActivity extends AlertActivity
finish();
return;
}
- final String suspendedPackage = intent.getStringExtra(EXTRA_SUSPENDED_PACKAGE);
- final String suspendingPackage = intent.getStringExtra(EXTRA_SUSPENDING_PACKAGE);
+ mSuspendedPackage = intent.getStringExtra(EXTRA_SUSPENDED_PACKAGE);
+ mSuspendingPackage = intent.getStringExtra(EXTRA_SUSPENDING_PACKAGE);
mSuppliedDialogInfo = intent.getParcelableExtra(EXTRA_DIALOG_INFO);
+ mOnUnsuspend = intent.getParcelableExtra(EXTRA_UNSUSPEND_INTENT);
if (mSuppliedDialogInfo != null) {
try {
- mSuspendingAppResources = mPm.getResourcesForApplicationAsUser(suspendingPackage,
+ mSuspendingAppResources = mPm.getResourcesForApplicationAsUser(mSuspendingPackage,
mUserId);
} catch (PackageManager.NameNotFoundException ne) {
- Slog.e(TAG, "Could not find resources for " + suspendingPackage, ne);
+ Slog.e(TAG, "Could not find resources for " + mSuspendingPackage, ne);
}
}
+ mNeutralButtonAction = (mSuppliedDialogInfo != null)
+ ? mSuppliedDialogInfo.getNeutralButtonAction() : BUTTON_ACTION_MORE_DETAILS;
+ mMoreDetailsIntent = (mNeutralButtonAction == BUTTON_ACTION_MORE_DETAILS)
+ ? getMoreDetailsActivity() : null;
final AlertController.AlertParams ap = mAlertParams;
ap.mIcon = resolveIcon();
ap.mTitle = resolveTitle();
- ap.mMessage = resolveDialogMessage(suspendingPackage, suspendedPackage);
+ ap.mMessage = resolveDialogMessage();
ap.mPositiveButtonText = getString(android.R.string.ok);
- mMoreDetailsIntent = getMoreDetailsActivity(suspendingPackage, suspendedPackage, mUserId);
- if (mMoreDetailsIntent != null) {
- ap.mNeutralButtonText = resolveNeutralButtonText();
- }
+ ap.mNeutralButtonText = resolveNeutralButtonText();
ap.mPositiveButtonListener = ap.mNeutralButtonListener = this;
setupAlert();
}
@@ -181,21 +215,62 @@ public class SuspendedAppActivity extends AlertActivity
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case AlertDialog.BUTTON_NEUTRAL:
- startActivityAsUser(mMoreDetailsIntent, mOptions, UserHandle.of(mUserId));
- Slog.i(TAG, "Started activity: " + mMoreDetailsIntent.getAction()
- + " in user " + mUserId);
+ switch (mNeutralButtonAction) {
+ case BUTTON_ACTION_MORE_DETAILS:
+ if (mMoreDetailsIntent != null) {
+ startActivityAsUser(mMoreDetailsIntent, mOptions,
+ UserHandle.of(mUserId));
+ } else {
+ Slog.wtf(TAG, "Neutral button should not have existed!");
+ }
+ break;
+ case BUTTON_ACTION_UNSUSPEND:
+ final IPackageManager ipm = AppGlobals.getPackageManager();
+ try {
+ final String[] errored = ipm.setPackagesSuspendedAsUser(
+ new String[]{mSuspendedPackage}, false, null, null, null,
+ mSuspendingPackage, mUserId);
+ if (ArrayUtils.contains(errored, mSuspendedPackage)) {
+ Slog.e(TAG, "Could not unsuspend " + mSuspendedPackage);
+ break;
+ }
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Can't talk to system process", re);
+ break;
+ }
+ final Intent reportUnsuspend = new Intent()
+ .setAction(Intent.ACTION_PACKAGE_UNSUSPENDED_MANUALLY)
+ .putExtra(Intent.EXTRA_PACKAGE_NAME, mSuspendedPackage)
+ .setPackage(mSuspendingPackage)
+ .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+ sendBroadcastAsUser(reportUnsuspend, UserHandle.of(mUserId));
+
+ if (mOnUnsuspend != null) {
+ try {
+ mOnUnsuspend.sendIntent(this, 0, null, null, null);
+ } catch (IntentSender.SendIntentException e) {
+ Slog.e(TAG, "Error while starting intent " + mOnUnsuspend, e);
+ }
+ }
+ break;
+ default:
+ Slog.e(TAG, "Unexpected action on neutral button: " + mNeutralButtonAction);
+ break;
+ }
break;
}
finish();
}
public static Intent createSuspendedAppInterceptIntent(String suspendedPackage,
- String suspendingPackage, SuspendDialogInfo dialogInfo, Bundle options, int userId) {
+ String suspendingPackage, SuspendDialogInfo dialogInfo, Bundle options,
+ IntentSender onUnsuspend, int userId) {
return new Intent()
.setClassName("android", SuspendedAppActivity.class.getName())
.putExtra(EXTRA_SUSPENDED_PACKAGE, suspendedPackage)
.putExtra(EXTRA_DIALOG_INFO, dialogInfo)
.putExtra(EXTRA_SUSPENDING_PACKAGE, suspendingPackage)
+ .putExtra(EXTRA_UNSUSPEND_INTENT, onUnsuspend)
.putExtra(EXTRA_ACTIVITY_OPTIONS, options)
.putExtra(Intent.EXTRA_USER_ID, userId)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
diff --git a/core/proto/android/server/usagestatsservice_v2.proto b/core/proto/android/server/usagestatsservice_v2.proto
index a28fcf3589f1..24b0728c29ec 100644
--- a/core/proto/android/server/usagestatsservice_v2.proto
+++ b/core/proto/android/server/usagestatsservice_v2.proto
@@ -99,6 +99,7 @@ message EventObfuscatedProto {
optional int32 instance_id = 10;
optional int32 task_root_package_token = 11;
optional int32 task_root_class_token = 12;
+ optional int32 locus_id_token = 13;
}
/**
@@ -117,6 +118,7 @@ message PendingEventProto {
optional int32 instance_id = 10;
optional string task_root_package = 11;
optional string task_root_class = 12;
+ optional string locus_id = 13;
}
/**
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4595bab82465..c069c82d3a1d 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -53,6 +53,7 @@
<protected-broadcast android:name="android.intent.action.PACKAGE_VERIFIED" />
<protected-broadcast android:name="android.intent.action.PACKAGES_SUSPENDED" />
<protected-broadcast android:name="android.intent.action.PACKAGES_UNSUSPENDED" />
+ <protected-broadcast android:name="android.intent.action.PACKAGE_UNSUSPENDED_MANUALLY" />
<protected-broadcast android:name="android.intent.action.DISTRACTING_PACKAGES_CHANGED" />
<protected-broadcast android:name="android.intent.action.ACTION_PREFERRED_ACTIVITY_CHANGED" />
<protected-broadcast android:name="android.intent.action.UID_REMOVED" />
@@ -5046,12 +5047,6 @@
android:process=":ui">
</activity>
- <activity android:name="com.android.internal.app.BlockedAppActivity"
- android:theme="@style/Theme.Dialog.Confirmation"
- android:excludeFromRecents="true"
- android:process=":ui">
- </activity>
-
<activity android:name="com.android.settings.notification.NotificationAccessConfirmationActivity"
android:theme="@style/Theme.Dialog.Confirmation"
android:excludeFromRecents="true">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index be2b678565d3..83ef456cbbcf 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4923,6 +4923,8 @@
</string>
<!-- Title of the button to show users more details about why the app has been suspended [CHAR LIMIT=50]-->
<string name="app_suspended_more_details">Learn more</string>
+ <!-- Title of the button to unsuspend a suspended app immediately [CHAR LIMIT=50]-->
+ <string name="app_suspended_unsuspend_message">Unpause app</string>
<!-- Title of a dialog. The string is asking if the user wants to turn on their work profile, which contains work apps that are managed by their employer. "Work" is an adjective. [CHAR LIMIT=30] -->
<string name="work_mode_off_title">Turn on work profile?</string>
@@ -4931,13 +4933,6 @@
<!-- Title for button to turn on work profile. [CHAR LIMIT=NONE] -->
<string name="work_mode_turn_on">Turn on</string>
- <!-- Title of the dialog that is shown when the user tries to launch a suspended application [CHAR LIMIT=50] -->
- <string name="app_blocked_title">App is not available</string>
- <!-- Default message shown in the dialog that is shown when the user tries to launch a suspended application [CHAR LIMIT=NONE] -->
- <string name="app_blocked_message">
- <xliff:g id="app_name" example="Gmail">%1$s</xliff:g> is not available right now.
- </string>
-
<!-- Message displayed in dialog when app is too old to run on this verison of android. [CHAR LIMIT=NONE] -->
<string name="deprecated_target_sdk_message">This app was built for an older version of Android and may not work properly. Try checking for updates, or contact the developer.</string>
<!-- Title for button to see application detail in app store which it came from - it may allow user to update to newer version. [CHAR LIMIT=50] -->
@@ -5318,7 +5313,8 @@
<string name="accessibility_system_action_lock_screen_label">Lock Screen</string>
<!-- Label for taking screenshot action [CHAR LIMIT=NONE] -->
<string name="accessibility_system_action_screenshot_label">Screenshot</string>
-
+ <!-- Label for showing accessibility menu action [CHAR LIMIT=NONE] -->
+ <string name="accessibility_system_action_accessibility_menu_label">Accessibility Menu</string>
<!-- Accessibility description of caption view -->
<string name="accessibility_freeform_caption">Caption bar of <xliff:g id="app_name">%1$s</xliff:g>.</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 18ca003dd8c6..9414cdba92f5 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3039,11 +3039,9 @@
<java-symbol type="string" name="app_suspended_title" />
<java-symbol type="string" name="app_suspended_more_details" />
+ <java-symbol type="string" name="app_suspended_unsuspend_message" />
<java-symbol type="string" name="app_suspended_default_message" />
- <java-symbol type="string" name="app_blocked_title" />
- <java-symbol type="string" name="app_blocked_message" />
-
<!-- Used internally for assistant to launch activity transitions -->
<java-symbol type="id" name="cross_task_transition" />
@@ -3804,6 +3802,7 @@
<java-symbol type="string" name="accessibility_system_action_recents_label" />
<java-symbol type="string" name="accessibility_system_action_screenshot_label" />
<java-symbol type="string" name="accessibility_system_action_toggle_split_screen_label" />
+ <java-symbol type="string" name="accessibility_system_action_accessibility_menu_label" />
<java-symbol type="string" name="accessibility_freeform_caption" />
diff --git a/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java b/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
index e48f1c3a89c7..c0d9be5dde59 100644
--- a/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
+++ b/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
@@ -18,12 +18,9 @@ package android.content.integrity;
import static android.content.integrity.TestUtils.assertExpectException;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
import android.content.integrity.AtomicFormula.BooleanAtomicFormula;
-import android.content.integrity.AtomicFormula.IntAtomicFormula;
import android.content.integrity.AtomicFormula.StringAtomicFormula;
import android.os.Parcel;
@@ -36,19 +33,93 @@ public class AtomicFormulaTest {
@Test
public void testValidAtomicFormula_stringValue() {
+ String packageName = "com.test.app";
StringAtomicFormula stringAtomicFormula =
new StringAtomicFormula(
- AtomicFormula.PACKAGE_NAME, "com.test.app", /* isHashedValue= */ false);
+ AtomicFormula.PACKAGE_NAME, packageName, /* isHashedValue= */false);
- assertEquals(AtomicFormula.PACKAGE_NAME, stringAtomicFormula.getKey());
+ assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.PACKAGE_NAME);
+ assertThat(stringAtomicFormula.getValue()).isEqualTo(packageName);
+ assertThat(stringAtomicFormula.getIsHashedValue()).isFalse();
}
@Test
- public void testValidAtomicFormula_intValue() {
- IntAtomicFormula intAtomicFormula =
- new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LE, 1);
+ public void testValidAtomicFormula_stringValue_autoHash_packageNameLessThanLimit() {
+ String packageName = "com.test.app";
+ StringAtomicFormula stringAtomicFormula =
+ new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, packageName);
+
+ assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.PACKAGE_NAME);
+ assertThat(stringAtomicFormula.getValue()).isEqualTo(packageName);
+ assertThat(stringAtomicFormula.getIsHashedValue()).isFalse();
+ }
+
+ @Test
+ public void testValidAtomicFormula_stringValue_autoHash_longPackageName() {
+ String packageName = "com.test.app.test.app.test.app.test.app.test.app";
+ StringAtomicFormula stringAtomicFormula =
+ new StringAtomicFormula(AtomicFormula.PACKAGE_NAME, packageName);
+
+ assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.PACKAGE_NAME);
+ assertThat(stringAtomicFormula.getValue()).doesNotMatch(packageName);
+ assertThat(stringAtomicFormula.getIsHashedValue()).isTrue();
+ }
+
+ @Test
+ public void testValidAtomicFormula_stringValue_autoHash_installerNameLessThanLimit() {
+ String installerName = "com.test.app";
+ StringAtomicFormula stringAtomicFormula =
+ new StringAtomicFormula(AtomicFormula.INSTALLER_NAME, installerName);
+
+
+ assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.INSTALLER_NAME);
+ assertThat(stringAtomicFormula.getValue()).isEqualTo(installerName);
+ assertThat(stringAtomicFormula.getIsHashedValue()).isFalse();
+ }
+
+ @Test
+ public void testValidAtomicFormula_stringValue_autoHash_longInstallerName() {
+ String installerName = "com.test.app.test.app.test.app.test.app.test.app";
+ StringAtomicFormula stringAtomicFormula =
+ new StringAtomicFormula(AtomicFormula.INSTALLER_NAME, installerName);
- assertEquals(AtomicFormula.VERSION_CODE, intAtomicFormula.getKey());
+ assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.INSTALLER_NAME);
+ assertThat(stringAtomicFormula.getValue()).doesNotMatch(installerName);
+ assertThat(stringAtomicFormula.getIsHashedValue()).isTrue();
+ }
+
+ @Test
+ public void testValidAtomicFormula_stringValue_appCertificateAutoHashed() {
+ String appCert = "cert";
+ StringAtomicFormula stringAtomicFormula =
+ new StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, appCert);
+
+ assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.APP_CERTIFICATE);
+ assertThat(stringAtomicFormula.getValue()).doesNotMatch(appCert);
+ assertThat(stringAtomicFormula.getIsHashedValue()).isTrue();
+ }
+
+ @Test
+ public void testValidAtomicFormula_stringValue_installerCertificateAutoHashed() {
+ String installerCert = "cert";
+ StringAtomicFormula stringAtomicFormula =
+ new StringAtomicFormula(AtomicFormula.INSTALLER_CERTIFICATE,
+ installerCert);
+
+ assertThat(stringAtomicFormula.getKey()).isEqualTo(
+ AtomicFormula.INSTALLER_CERTIFICATE);
+ assertThat(stringAtomicFormula.getValue()).doesNotMatch(installerCert);
+ assertThat(stringAtomicFormula.getIsHashedValue()).isTrue();
+ }
+
+ @Test
+ public void testValidAtomicFormula_longValue() {
+ AtomicFormula.LongAtomicFormula longAtomicFormula =
+ new AtomicFormula.LongAtomicFormula(
+ AtomicFormula.VERSION_CODE, AtomicFormula.GTE, 1);
+
+ assertThat(longAtomicFormula.getKey()).isEqualTo(AtomicFormula.VERSION_CODE);
+ assertThat(longAtomicFormula.getValue()).isEqualTo(1);
}
@Test
@@ -56,7 +127,8 @@ public class AtomicFormulaTest {
BooleanAtomicFormula atomicFormula =
new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true);
- assertEquals(AtomicFormula.PRE_INSTALLED, atomicFormula.getKey());
+ assertThat(atomicFormula.getKey()).isEqualTo(AtomicFormula.PRE_INSTALLED);
+ assertThat(atomicFormula.getValue()).isTrue();
}
@Test
@@ -73,12 +145,14 @@ public class AtomicFormulaTest {
}
@Test
- public void testInvalidAtomicFormula_intValue() {
+ public void testInvalidAtomicFormula_longValue() {
assertExpectException(
IllegalArgumentException.class,
/* expectedExceptionMessageRegex */
- String.format("Key PACKAGE_NAME cannot be used with IntAtomicFormula"),
- () -> new IntAtomicFormula(AtomicFormula.PACKAGE_NAME, AtomicFormula.EQ, 1));
+ String.format("Key PACKAGE_NAME cannot be used with LongAtomicFormula"),
+ () ->
+ new AtomicFormula.LongAtomicFormula(
+ AtomicFormula.PACKAGE_NAME, AtomicFormula.EQ, 1));
}
@Test
@@ -91,197 +165,174 @@ public class AtomicFormulaTest {
}
@Test
- public void testIsSatisfiable_string_true() {
- StringAtomicFormula stringAtomicFormula =
+ public void testParcelUnparcel_string() {
+ StringAtomicFormula formula =
new StringAtomicFormula(
- AtomicFormula.PACKAGE_NAME, "com.test.app", /* isHashedValue= */ false);
- AppInstallMetadata appInstallMetadata =
- getAppInstallMetadataBuilder().setPackageName("com.test.app").build();
+ AtomicFormula.PACKAGE_NAME, "abc", /* isHashedValue= */ false);
+ Parcel p = Parcel.obtain();
+ formula.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ StringAtomicFormula newFormula = StringAtomicFormula.CREATOR.createFromParcel(p);
- assertTrue(stringAtomicFormula.isSatisfied(appInstallMetadata));
+ assertThat(newFormula).isEqualTo(formula);
}
@Test
- public void testIsSatisfiable_string_false() {
- StringAtomicFormula stringAtomicFormula =
- new StringAtomicFormula(
- AtomicFormula.PACKAGE_NAME, "com.test.app", /* isHashedValue= */ false);
- AppInstallMetadata appInstallMetadata =
- getAppInstallMetadataBuilder().setPackageName("com.foo.bar").build();
+ public void testParcelUnparcel_int() {
+ AtomicFormula.LongAtomicFormula formula =
+ new AtomicFormula.LongAtomicFormula(
+ AtomicFormula.VERSION_CODE, AtomicFormula.GT, 1);
+ Parcel p = Parcel.obtain();
+ formula.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ AtomicFormula.LongAtomicFormula newFormula =
+ AtomicFormula.LongAtomicFormula.CREATOR.createFromParcel(p);
- assertFalse(stringAtomicFormula.isSatisfied(appInstallMetadata));
+ assertThat(newFormula).isEqualTo(formula);
}
@Test
- public void testIsSatisfiable_int_eq_true() {
- IntAtomicFormula intAtomicFormula =
- new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 0);
- AppInstallMetadata appInstallMetadata =
- getAppInstallMetadataBuilder().setVersionCode(0).build();
+ public void testParcelUnparcel_bool() {
+ BooleanAtomicFormula formula = new BooleanAtomicFormula(
+ AtomicFormula.PRE_INSTALLED, true);
+ Parcel p = Parcel.obtain();
+ formula.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ BooleanAtomicFormula newFormula = BooleanAtomicFormula.CREATOR.createFromParcel(p);
- assertTrue(intAtomicFormula.isSatisfied(appInstallMetadata));
+ assertThat(newFormula).isEqualTo(formula);
}
@Test
- public void testIsSatisfiable_int_eq_false() {
- IntAtomicFormula intAtomicFormula =
- new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 0);
- AppInstallMetadata appInstallMetadata =
- getAppInstallMetadataBuilder().setVersionCode(1).build();
-
- assertFalse(intAtomicFormula.isSatisfied(appInstallMetadata));
+ public void testInvalidAtomicFormula_invalidKey() {
+ assertExpectException(
+ IllegalArgumentException.class,
+ /* expectedExceptionMessageRegex */ "Unknown key: -1",
+ () -> new AtomicFormula.LongAtomicFormula(/* key= */ -1, AtomicFormula.EQ, 0));
}
@Test
- public void testIsSatisfiable_int_gt_true() {
- IntAtomicFormula intAtomicFormula =
- new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GT, 0);
- AppInstallMetadata appInstallMetadata =
- getAppInstallMetadataBuilder().setVersionCode(1).build();
-
- assertTrue(intAtomicFormula.isSatisfied(appInstallMetadata));
+ public void testInvalidAtomicFormula_invalidOperator() {
+ assertExpectException(
+ IllegalArgumentException.class,
+ /* expectedExceptionMessageRegex */ "Unknown operator: -1",
+ () ->
+ new AtomicFormula.LongAtomicFormula(
+ AtomicFormula.VERSION_CODE, /* operator= */ -1, 0));
}
@Test
- public void testIsSatisfiable_int_gt_false() {
- IntAtomicFormula intAtomicFormula =
- new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GT, 1);
+ public void testFormulaMatches_string_true() {
+ StringAtomicFormula stringAtomicFormula =
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME, "com.test.app", /* isHashedValue= */
+ false);
AppInstallMetadata appInstallMetadata =
- getAppInstallMetadataBuilder().setVersionCode(0).build();
+ getAppInstallMetadataBuilder().setPackageName("com.test.app").build();
- assertFalse(intAtomicFormula.isSatisfied(appInstallMetadata));
+ assertThat(stringAtomicFormula.matches(appInstallMetadata)).isTrue();
}
@Test
- public void testIsSatisfiable_int_ge_true() {
- IntAtomicFormula intAtomicFormula =
- new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GE, 0);
+ public void testFormulaMatches_string_false() {
+ StringAtomicFormula stringAtomicFormula =
+ new StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME, "com.test.app", /* isHashedValue= */
+ false);
AppInstallMetadata appInstallMetadata =
- getAppInstallMetadataBuilder().setVersionCode(1).build();
+ getAppInstallMetadataBuilder().setPackageName("com.foo.bar").build();
- assertTrue(intAtomicFormula.isSatisfied(appInstallMetadata));
+ assertThat(stringAtomicFormula.matches(appInstallMetadata)).isFalse();
}
@Test
- public void testIsSatisfiable_int_ge_false() {
- IntAtomicFormula intAtomicFormula =
- new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GE, 1);
+ public void testFormulaMatches_long_eq_true() {
+ AtomicFormula.LongAtomicFormula longAtomicFormula =
+ new AtomicFormula.LongAtomicFormula(
+ AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 0);
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setVersionCode(0).build();
- assertFalse(intAtomicFormula.isSatisfied(appInstallMetadata));
+ assertThat(longAtomicFormula.matches(appInstallMetadata)).isTrue();
}
@Test
- public void testIsSatisfiable_int_lt_true() {
- IntAtomicFormula intAtomicFormula =
- new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LT, 1);
+ public void testFormulaMatches_long_eq_false() {
+ AtomicFormula.LongAtomicFormula longAtomicFormula =
+ new AtomicFormula.LongAtomicFormula(
+ AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 0);
AppInstallMetadata appInstallMetadata =
- getAppInstallMetadataBuilder().setVersionCode(0).build();
+ getAppInstallMetadataBuilder().setVersionCode(1).build();
- assertTrue(intAtomicFormula.isSatisfied(appInstallMetadata));
+ assertThat(longAtomicFormula.matches(appInstallMetadata)).isFalse();
}
@Test
- public void testIsSatisfiable_int_lt_false() {
- IntAtomicFormula intAtomicFormula =
- new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LT, 1);
+ public void testFormulaMatches_long_gt_true() {
+ AtomicFormula.LongAtomicFormula longAtomicFormula =
+ new AtomicFormula.LongAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GT,
+ 0);
AppInstallMetadata appInstallMetadata =
- getAppInstallMetadataBuilder().setVersionCode(2).build();
+ getAppInstallMetadataBuilder().setVersionCode(1).build();
- assertFalse(intAtomicFormula.isSatisfied(appInstallMetadata));
+ assertThat(longAtomicFormula.matches(appInstallMetadata)).isTrue();
}
@Test
- public void testIsSatisfiable_int_le_true() {
- IntAtomicFormula intAtomicFormula =
- new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LE, 1);
+ public void testFormulaMatches_long_gt_false() {
+ AtomicFormula.LongAtomicFormula longAtomicFormula =
+ new AtomicFormula.LongAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.GT,
+ 1);
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setVersionCode(0).build();
- assertTrue(intAtomicFormula.isSatisfied(appInstallMetadata));
+ assertThat(longAtomicFormula.matches(appInstallMetadata)).isFalse();
}
@Test
- public void testIsSatisfiable_int_le_false() {
- IntAtomicFormula intAtomicFormula =
- new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LE, 1);
- AppInstallMetadata appInstallMetadata =
+ public void testFormulaMatches_long_gte_true() {
+ AtomicFormula.LongAtomicFormula longAtomicFormula =
+ new AtomicFormula.LongAtomicFormula(
+ AtomicFormula.VERSION_CODE, AtomicFormula.GTE, 1);
+
+ AppInstallMetadata appInstallMetadata1 =
+ getAppInstallMetadataBuilder().setVersionCode(1).build();
+ assertThat(longAtomicFormula.matches(appInstallMetadata1)).isTrue();
+
+ AppInstallMetadata appInstallMetadata2 =
getAppInstallMetadataBuilder().setVersionCode(2).build();
+ assertThat(longAtomicFormula.matches(appInstallMetadata2)).isTrue();
+ }
- assertFalse(intAtomicFormula.isSatisfied(appInstallMetadata));
+ @Test
+ public void testFormulaMatches_long_gte_false() {
+ AtomicFormula.LongAtomicFormula longAtomicFormula =
+ new AtomicFormula.LongAtomicFormula(
+ AtomicFormula.VERSION_CODE, AtomicFormula.GTE, 1);
+ AppInstallMetadata appInstallMetadata =
+ getAppInstallMetadataBuilder().setVersionCode(0).build();
+
+ assertThat(longAtomicFormula.matches(appInstallMetadata)).isFalse();
}
@Test
- public void testIsSatisfiable_bool_true() {
+ public void testFormulaMatches_bool_true() {
BooleanAtomicFormula boolFormula =
new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true);
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setIsPreInstalled(true).build();
- assertTrue(boolFormula.isSatisfied(appInstallMetadata));
+ assertThat(boolFormula.matches(appInstallMetadata)).isTrue();
}
@Test
- public void testIsSatisfiable_bool_false() {
+ public void testFormulaMatches_bool_false() {
BooleanAtomicFormula boolFormula =
new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true);
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setIsPreInstalled(false).build();
- assertFalse(boolFormula.isSatisfied(appInstallMetadata));
- }
-
- @Test
- public void testParcelUnparcel_string() {
- StringAtomicFormula formula =
- new StringAtomicFormula(
- AtomicFormula.PACKAGE_NAME, "abc", /* isHashedValue= */ false);
- Parcel p = Parcel.obtain();
- formula.writeToParcel(p, 0);
- p.setDataPosition(0);
- StringAtomicFormula newFormula = StringAtomicFormula.CREATOR.createFromParcel(p);
-
- assertEquals(formula, newFormula);
- }
-
- @Test
- public void testParcelUnparcel_int() {
- IntAtomicFormula formula =
- new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LT, 1);
- Parcel p = Parcel.obtain();
- formula.writeToParcel(p, 0);
- p.setDataPosition(0);
- IntAtomicFormula newFormula = IntAtomicFormula.CREATOR.createFromParcel(p);
-
- assertEquals(formula, newFormula);
- }
-
- @Test
- public void testParcelUnparcel_bool() {
- BooleanAtomicFormula formula = new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true);
- Parcel p = Parcel.obtain();
- formula.writeToParcel(p, 0);
- p.setDataPosition(0);
- BooleanAtomicFormula newFormula = BooleanAtomicFormula.CREATOR.createFromParcel(p);
-
- assertEquals(formula, newFormula);
- }
-
- @Test
- public void testInvalidAtomicFormula_invalidKey() {
- assertExpectException(
- IllegalArgumentException.class,
- /* expectedExceptionMessageRegex */ "Unknown key: -1",
- () -> new IntAtomicFormula(/* key= */ -1, AtomicFormula.EQ, 0));
- }
-
- @Test
- public void testInvalidAtomicFormula_invalidOperator() {
- assertExpectException(
- IllegalArgumentException.class,
- /* expectedExceptionMessageRegex */ "Unknown operator: -1",
- () -> new IntAtomicFormula(AtomicFormula.VERSION_CODE, /* operator= */ -1, 0));
+ assertThat(boolFormula.matches(appInstallMetadata)).isFalse();
}
/** Returns a builder with all fields filled with some dummy data. */
diff --git a/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java b/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java
index 927e4dbb5200..fa3d671c09e5 100644
--- a/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java
+++ b/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java
@@ -18,9 +18,9 @@ package android.content.integrity;
import static android.content.integrity.TestUtils.assertExpectException;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
import android.os.Parcel;
@@ -38,7 +38,7 @@ public class CompoundFormulaTest {
new AtomicFormula.StringAtomicFormula(
AtomicFormula.PACKAGE_NAME, "test1", /* isHashedValue= */ false);
private static final AtomicFormula ATOMIC_FORMULA_2 =
- new AtomicFormula.IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1);
+ new AtomicFormula.LongAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1);
@Test
public void testValidCompoundFormula() {
@@ -75,163 +75,156 @@ public class CompoundFormulaTest {
}
@Test
- public void testIsSatisfiable_notFalse_true() {
- CompoundFormula compoundFormula =
- new CompoundFormula(CompoundFormula.NOT, Arrays.asList(ATOMIC_FORMULA_1));
- AppInstallMetadata appInstallMetadata =
- getAppInstallMetadataBuilder().setPackageName("test2").build();
- // validate assumptions about the metadata
- assertFalse(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
+ public void testParcelUnparcel() {
+ CompoundFormula formula =
+ new CompoundFormula(
+ CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_2, ATOMIC_FORMULA_1));
+ Parcel p = Parcel.obtain();
+ formula.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ CompoundFormula newFormula = CompoundFormula.CREATOR.createFromParcel(p);
+
+ assertEquals(formula, newFormula);
+ }
- assertTrue(compoundFormula.isSatisfied(appInstallMetadata));
+ @Test
+ public void testInvalidCompoundFormula_invalidConnector() {
+ assertExpectException(
+ IllegalArgumentException.class,
+ /* expectedExceptionMessageRegex */ "Unknown connector: -1",
+ () ->
+ new CompoundFormula(
+ /* connector= */ -1,
+ Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
}
@Test
- public void testIsSatisfiable_notTrue_false() {
+ public void testFormulaMatches_notFalse_true() {
+ AppInstallMetadata appInstallMetadata =
+ getAppInstallMetadataBuilder().setPackageName("test2").build();
+
+ assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isFalse();
+
CompoundFormula compoundFormula =
new CompoundFormula(CompoundFormula.NOT, Arrays.asList(ATOMIC_FORMULA_1));
+ assertThat(compoundFormula.matches(appInstallMetadata)).isTrue();
+ }
+
+ @Test
+ public void testFormulaMatches_notTrue_false() {
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test1").build();
- // validate assumptions about the metadata
- assertTrue(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
- assertFalse(compoundFormula.isSatisfied(appInstallMetadata));
+ assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isTrue();
+
+ CompoundFormula compoundFormula =
+ new CompoundFormula(CompoundFormula.NOT, Arrays.asList(ATOMIC_FORMULA_1));
+ assertThat(compoundFormula.matches(appInstallMetadata)).isFalse();
}
@Test
- public void testIsSatisfiable_trueAndTrue_true() {
+ public void testFormulaMatches_trueAndTrue_true() {
CompoundFormula compoundFormula =
new CompoundFormula(
CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(1).build();
// validate assumptions about the metadata
- assertTrue(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
- assertTrue(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
+ assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isTrue();
+ assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isTrue();
- assertTrue(compoundFormula.isSatisfied(appInstallMetadata));
+ assertThat(compoundFormula.matches(appInstallMetadata)).isTrue();
}
@Test
- public void testIsSatisfiable_trueAndFalse_false() {
+ public void testFormulaMatches_trueAndFalse_false() {
CompoundFormula compoundFormula =
new CompoundFormula(
CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(2).build();
- // validate assumptions about the metadata
- assertTrue(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
- assertFalse(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
- assertFalse(compoundFormula.isSatisfied(appInstallMetadata));
+ assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isTrue();
+ assertThat(ATOMIC_FORMULA_2.matches(appInstallMetadata)).isFalse();
+ assertThat(compoundFormula.matches(appInstallMetadata)).isFalse();
}
@Test
- public void testIsSatisfiable_falseAndTrue_false() {
+ public void testFormulaMatches_falseAndTrue_false() {
CompoundFormula compoundFormula =
new CompoundFormula(
CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(1).build();
- // validate assumptions about the metadata
- assertFalse(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
- assertTrue(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
- assertFalse(compoundFormula.isSatisfied(appInstallMetadata));
+ assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isFalse();
+ assertThat(ATOMIC_FORMULA_2.matches(appInstallMetadata)).isTrue();
+ assertThat(compoundFormula.matches(appInstallMetadata)).isFalse();
}
@Test
- public void testIsSatisfiable_falseAndFalse_false() {
+ public void testFormulaMatches_falseAndFalse_false() {
CompoundFormula compoundFormula =
new CompoundFormula(
CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(2).build();
- // validate assumptions about the metadata
- assertFalse(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
- assertFalse(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
- assertFalse(compoundFormula.isSatisfied(appInstallMetadata));
+ assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isFalse();
+ assertThat(ATOMIC_FORMULA_2.matches(appInstallMetadata)).isFalse();
+ assertThat(compoundFormula.matches(appInstallMetadata)).isFalse();
}
@Test
- public void testIsSatisfiable_trueOrTrue_true() {
+ public void testFormulaMatches_trueOrTrue_true() {
CompoundFormula compoundFormula =
new CompoundFormula(
CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(1).build();
- // validate assumptions about the metadata
- assertTrue(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
- assertTrue(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
- assertTrue(compoundFormula.isSatisfied(appInstallMetadata));
+ assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isTrue();
+ assertThat(ATOMIC_FORMULA_2.matches(appInstallMetadata)).isTrue();
+ assertThat(compoundFormula.matches(appInstallMetadata)).isTrue();
}
@Test
- public void testIsSatisfiable_trueOrFalse_true() {
+ public void testFormulaMatches_trueOrFalse_true() {
CompoundFormula compoundFormula =
new CompoundFormula(
CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test1").setVersionCode(2).build();
- // validate assumptions about the metadata
- assertTrue(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
- assertFalse(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
- assertTrue(compoundFormula.isSatisfied(appInstallMetadata));
+ assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isTrue();
+ assertThat(ATOMIC_FORMULA_2.matches(appInstallMetadata)).isFalse();
+ assertThat(compoundFormula.matches(appInstallMetadata)).isTrue();
}
@Test
- public void testIsSatisfiable_falseOrTrue_true() {
+ public void testFormulaMatches_falseOrTrue_true() {
CompoundFormula compoundFormula =
new CompoundFormula(
CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(1).build();
- // validate assumptions about the metadata
- assertFalse(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
- assertTrue(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
- assertTrue(compoundFormula.isSatisfied(appInstallMetadata));
+ assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isFalse();
+ assertThat(ATOMIC_FORMULA_2.matches(appInstallMetadata)).isTrue();
+ assertThat(compoundFormula.matches(appInstallMetadata)).isTrue();
}
@Test
- public void testIsSatisfiable_falseOrFalse_false() {
+ public void testFormulaMatches_falseOrFalse_false() {
CompoundFormula compoundFormula =
new CompoundFormula(
CompoundFormula.OR, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
AppInstallMetadata appInstallMetadata =
getAppInstallMetadataBuilder().setPackageName("test2").setVersionCode(2).build();
- // validate assumptions about the metadata
- assertFalse(ATOMIC_FORMULA_1.isSatisfied(appInstallMetadata));
- assertFalse(ATOMIC_FORMULA_2.isSatisfied(appInstallMetadata));
-
- assertFalse(compoundFormula.isSatisfied(appInstallMetadata));
- }
-
- @Test
- public void testParcelUnparcel() {
- CompoundFormula formula =
- new CompoundFormula(
- CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_2, ATOMIC_FORMULA_1));
- Parcel p = Parcel.obtain();
- formula.writeToParcel(p, 0);
- p.setDataPosition(0);
- CompoundFormula newFormula = CompoundFormula.CREATOR.createFromParcel(p);
- assertEquals(formula, newFormula);
- }
-
- @Test
- public void testInvalidCompoundFormula_invalidConnector() {
- assertExpectException(
- IllegalArgumentException.class,
- /* expectedExceptionMessageRegex */ "Unknown connector: -1",
- () ->
- new CompoundFormula(
- /* connector= */ -1,
- Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
+ assertThat(ATOMIC_FORMULA_1.matches(appInstallMetadata)).isFalse();
+ assertThat(ATOMIC_FORMULA_2.matches(appInstallMetadata)).isFalse();
+ assertThat(compoundFormula.matches(appInstallMetadata)).isFalse();
}
/** Returns a builder with all fields filled with some dummy data. */
diff --git a/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java b/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java
new file mode 100644
index 000000000000..c1806028f75b
--- /dev/null
+++ b/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2020 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.content.integrity;
+
+import static android.content.integrity.IntegrityFormula.COMPOUND_FORMULA_TAG;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class IntegrityFormulaTest {
+
+ @Test
+ public void createEqualsFormula_packageName() {
+ String packageName = "com.test.app";
+ IntegrityFormula formula =
+ IntegrityFormula.PACKAGE_NAME.equalTo(packageName);
+
+ AtomicFormula.StringAtomicFormula stringAtomicFormula =
+ (AtomicFormula.StringAtomicFormula) formula;
+
+ assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.PACKAGE_NAME);
+ assertThat(stringAtomicFormula.getValue()).isEqualTo(packageName);
+ assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(false);
+ }
+
+ @Test
+ public void createEqualsFormula_appCertificate() {
+ String appCertificate = "com.test.app";
+ IntegrityFormula formula =
+ IntegrityFormula.APP_CERTIFICATE.equalTo(appCertificate);
+
+ AtomicFormula.StringAtomicFormula stringAtomicFormula =
+ (AtomicFormula.StringAtomicFormula) formula;
+
+ assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.APP_CERTIFICATE);
+ assertThat(stringAtomicFormula.getValue()).doesNotMatch(appCertificate);
+ assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(true);
+ }
+
+ @Test
+ public void createEqualsFormula_installerName() {
+ String installerName = "com.test.app";
+ IntegrityFormula formula =
+ IntegrityFormula.INSTALLER_NAME.equalTo(installerName);
+
+ AtomicFormula.StringAtomicFormula stringAtomicFormula =
+ (AtomicFormula.StringAtomicFormula) formula;
+
+ assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.INSTALLER_NAME);
+ assertThat(stringAtomicFormula.getValue()).isEqualTo(installerName);
+ assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(false);
+ }
+
+ @Test
+ public void createEqualsFormula_installerCertificate() {
+ String installerCertificate = "com.test.app";
+ IntegrityFormula formula =
+ IntegrityFormula.INSTALLER_CERTIFICATE.equalTo(installerCertificate);
+
+ AtomicFormula.StringAtomicFormula stringAtomicFormula =
+ (AtomicFormula.StringAtomicFormula) formula;
+
+ assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.INSTALLER_CERTIFICATE);
+ assertThat(stringAtomicFormula.getValue()).doesNotMatch(installerCertificate);
+ assertThat(stringAtomicFormula.getIsHashedValue()).isEqualTo(true);
+ }
+
+ @Test
+ public void createEqualsFormula_versionCode() {
+ int versionCode = 12;
+ IntegrityFormula formula =
+ IntegrityFormula.VERSION_CODE.equalTo(versionCode);
+
+ AtomicFormula.LongAtomicFormula stringAtomicFormula =
+ (AtomicFormula.LongAtomicFormula) formula;
+
+ assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.VERSION_CODE);
+ assertThat(stringAtomicFormula.getValue()).isEqualTo(versionCode);
+ assertThat(stringAtomicFormula.getOperator()).isEqualTo(AtomicFormula.EQ);
+ }
+
+ @Test
+ public void createEqualsFormula_invalidKeyTypeForStringParameter() {
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> IntegrityFormula.PRE_INSTALLED.equalTo("wrongString"));
+ }
+
+ @Test
+ public void createEqualsFormula_invalidKeyTypeForLongParameter() {
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> IntegrityFormula.PACKAGE_NAME.equalTo(12));
+ }
+
+ @Test
+ public void createGreaterThanFormula_versionCode() {
+ int versionCode = 12;
+ IntegrityFormula formula =
+ IntegrityFormula.VERSION_CODE.greaterThan(versionCode);
+
+ AtomicFormula.LongAtomicFormula stringAtomicFormula =
+ (AtomicFormula.LongAtomicFormula) formula;
+
+ assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.VERSION_CODE);
+ assertThat(stringAtomicFormula.getValue()).isEqualTo(versionCode);
+ assertThat(stringAtomicFormula.getOperator()).isEqualTo(AtomicFormula.GT);
+ }
+
+ @Test
+ public void createGreaterThanFormula_invalidKeyTypeForLongParameter() {
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> IntegrityFormula.PACKAGE_NAME.greaterThan(12));
+ }
+
+ @Test
+ public void createGreaterThanOrEqualsToFormula_versionCode() {
+ int versionCode = 12;
+ IntegrityFormula formula =
+ IntegrityFormula.VERSION_CODE.greaterThanOrEquals(versionCode);
+
+ AtomicFormula.LongAtomicFormula stringAtomicFormula =
+ (AtomicFormula.LongAtomicFormula) formula;
+
+ assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.VERSION_CODE);
+ assertThat(stringAtomicFormula.getValue()).isEqualTo(versionCode);
+ assertThat(stringAtomicFormula.getOperator()).isEqualTo(AtomicFormula.GTE);
+ }
+
+ @Test
+ public void createGreaterThanOrEqualsToFormula_invalidKeyTypeForLongParameter() {
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> IntegrityFormula.PACKAGE_NAME.greaterThanOrEquals(12));
+ }
+
+ @Test
+ public void createIsTrueFormula_preInstalled() {
+ IntegrityFormula formula = IntegrityFormula.PRE_INSTALLED.equalTo(true);
+
+ AtomicFormula.BooleanAtomicFormula stringAtomicFormula =
+ (AtomicFormula.BooleanAtomicFormula) formula;
+
+ assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.PRE_INSTALLED);
+ assertThat(stringAtomicFormula.getValue()).isTrue();
+ }
+
+ @Test
+ public void createIsTrueFormula_invalidKeyTypeForBoolParameter() {
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> IntegrityFormula.PACKAGE_NAME.equalTo(true));
+ }
+
+ @Test
+ public void createAllFormula() {
+ String packageName = "com.test.package";
+ String certificateName = "certificate";
+ IntegrityFormula formula1 =
+ IntegrityFormula.PACKAGE_NAME.equalTo(packageName);
+ IntegrityFormula formula2 =
+ IntegrityFormula.APP_CERTIFICATE.equalTo(certificateName);
+
+ IntegrityFormula compoundFormula = IntegrityFormula.all(formula1, formula2);
+
+ assertThat(compoundFormula.getTag()).isEqualTo(COMPOUND_FORMULA_TAG);
+ }
+
+ @Test
+ public void createAnyFormula() {
+ String packageName = "com.test.package";
+ String certificateName = "certificate";
+ IntegrityFormula formula1 =
+ IntegrityFormula.PACKAGE_NAME.equalTo(packageName);
+ IntegrityFormula formula2 =
+ IntegrityFormula.APP_CERTIFICATE.equalTo(certificateName);
+
+ IntegrityFormula compoundFormula = IntegrityFormula.any(formula1, formula2);
+
+ assertThat(compoundFormula.getTag()).isEqualTo(COMPOUND_FORMULA_TAG);
+ }
+
+ @Test
+ public void createNotFormula() {
+ String packageName = "com.test.package";
+
+ IntegrityFormula compoundFormula =
+ IntegrityFormula.not(
+ IntegrityFormula.PACKAGE_NAME.equalTo(packageName));
+
+ assertThat(compoundFormula.getTag()).isEqualTo(COMPOUND_FORMULA_TAG);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/IntegrityUtilsTest.java b/core/tests/coretests/src/android/content/integrity/IntegrityUtilsTest.java
index ac7f8f98ab9b..639adf6a05d7 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/IntegrityUtilsTest.java
+++ b/core/tests/coretests/src/android/content/integrity/IntegrityUtilsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,48 +14,44 @@
* limitations under the License.
*/
-package com.android.server.integrity;
+package android.content.integrity;
-import static com.android.server.integrity.IntegrityUtils.getBytesFromHexDigest;
-import static com.android.server.integrity.IntegrityUtils.getHexDigest;
-import static com.android.server.testutils.TestUtils.assertExpectException;
+import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-
-import androidx.test.runner.AndroidJUnit4;
+import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
-/** Unit test for {@link com.android.server.integrity.IntegrityUtils} */
-@RunWith(AndroidJUnit4.class)
+/** Unit test for {@link IntegrityUtils} */
+@RunWith(JUnit4.class)
public class IntegrityUtilsTest {
private static final String HEX_DIGEST = "1234567890ABCDEF";
private static final byte[] BYTES =
- new byte[] {0x12, 0x34, 0x56, 0x78, (byte) 0x90, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF};
+ new byte[]{0x12, 0x34, 0x56, 0x78, (byte) 0x90, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF};
@Test
public void testGetBytesFromHexDigest() {
- assertArrayEquals(BYTES, getBytesFromHexDigest(HEX_DIGEST));
+ assertArrayEquals(BYTES, IntegrityUtils.getBytesFromHexDigest(HEX_DIGEST));
}
@Test
public void testGetHexDigest() {
- assertEquals(HEX_DIGEST, getHexDigest(BYTES));
+ assertThat(IntegrityUtils.getHexDigest(BYTES)).isEqualTo(HEX_DIGEST);
}
@Test
public void testInvalidHexDigest() {
- assertExpectException(
+ TestUtils.assertExpectException(
IllegalArgumentException.class,
"must have even length",
- () -> getBytesFromHexDigest("ABC"));
+ () -> IntegrityUtils.getBytesFromHexDigest("ABC"));
- assertExpectException(
+ TestUtils.assertExpectException(
IllegalArgumentException.class,
"Invalid hex char",
- () -> getBytesFromHexDigest("GH"));
+ () -> IntegrityUtils.getBytesFromHexDigest("GH"));
}
}
diff --git a/core/tests/coretests/src/android/content/integrity/RuleTest.java b/core/tests/coretests/src/android/content/integrity/RuleTest.java
index 19e74e6b93cc..8c4cfca39e90 100644
--- a/core/tests/coretests/src/android/content/integrity/RuleTest.java
+++ b/core/tests/coretests/src/android/content/integrity/RuleTest.java
@@ -35,11 +35,15 @@ public class RuleTest {
private static final @Rule.Effect int DENY_EFFECT = Rule.DENY;
private static final String PACKAGE_NAME = "com.test.app";
private static final String APP_CERTIFICATE = "test_cert";
- private static final Formula PACKAGE_NAME_ATOMIC_FORMULA =
- new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, PACKAGE_NAME,
+ private static final IntegrityFormula PACKAGE_NAME_ATOMIC_FORMULA =
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ PACKAGE_NAME,
/* isHashedValue= */ false);
- private static final Formula APP_CERTIFICATE_ATOMIC_FORMULA =
- new AtomicFormula.StringAtomicFormula(AtomicFormula.APP_CERTIFICATE, APP_CERTIFICATE,
+ private static final IntegrityFormula APP_CERTIFICATE_ATOMIC_FORMULA =
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.APP_CERTIFICATE,
+ APP_CERTIFICATE,
/* isHashedValue= */ false);
@Test
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 687535c3304b..0c5fe787bbbc 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -74,7 +74,7 @@ import java.util.function.Consumer;
* still return location results, but the exact location will be obfuscated to a coarse level of
* accuracy.
*/
-@SuppressWarnings({"deprecation", "DeprecatedIsStillUsed"})
+@SuppressWarnings({"deprecation"})
@SystemService(Context.LOCATION_SERVICE)
@RequiresFeature(PackageManager.FEATURE_LOCATION)
public class LocationManager {
diff --git a/location/java/android/location/LocationManagerInternal.java b/location/java/android/location/LocationManagerInternal.java
new file mode 100644
index 000000000000..44d9d2372665
--- /dev/null
+++ b/location/java/android/location/LocationManagerInternal.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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.location;
+
+
+import android.annotation.NonNull;
+
+/**
+ * Location manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class LocationManagerInternal {
+
+ /**
+ * Requests that a provider change its allowed state. A provider may or may not honor this
+ * request, and if the provider does change its state as a result, that may happen
+ * asynchronously after some delay.
+ *
+ * <p>Setting a provider's state to allowed implies that any consents or terms and conditions
+ * that may be necessary to allow the provider are agreed to. Setting a providers state to
+ * disallowed implies that any consents or terms and conditions have their agreement revoked.
+ *
+ * @param provider A location provider as listed by {@link LocationManager#getAllProviders()}
+ * @param allowed Whether the location provider is being requested to allow or disallow
+ * itself
+ * @throws IllegalArgumentException if provider is null
+ */
+ public abstract void requestSetProviderAllowed(@NonNull String provider, boolean allowed);
+}
diff --git a/location/java/com/android/internal/location/ILocationProvider.aidl b/location/java/com/android/internal/location/ILocationProvider.aidl
index 4246c6cd1004..b7817ff1e1fc 100644
--- a/location/java/com/android/internal/location/ILocationProvider.aidl
+++ b/location/java/com/android/internal/location/ILocationProvider.aidl
@@ -37,4 +37,6 @@ interface ILocationProvider {
@UnsupportedAppUsage
oneway void sendExtraCommand(String command, in Bundle extras);
+
+ oneway void requestSetAllowed(boolean allowed);
}
diff --git a/location/java/com/android/internal/location/ILocationProviderManager.aidl b/location/java/com/android/internal/location/ILocationProviderManager.aidl
index 85e18ba5ec4b..439039148773 100644
--- a/location/java/com/android/internal/location/ILocationProviderManager.aidl
+++ b/location/java/com/android/internal/location/ILocationProviderManager.aidl
@@ -29,7 +29,7 @@ interface ILocationProviderManager {
void onSetAdditionalProviderPackages(in List<String> packageNames);
@UnsupportedAppUsage
- void onSetEnabled(boolean enabled);
+ void onSetAllowed(boolean allowed);
@UnsupportedAppUsage
void onSetProperties(in ProviderProperties properties);
diff --git a/location/lib/api/current.txt b/location/lib/api/current.txt
index 5471bea549f4..49fcaabe981a 100644
--- a/location/lib/api/current.txt
+++ b/location/lib/api/current.txt
@@ -9,18 +9,21 @@ package com.android.location.provider {
public abstract class LocationProviderBase {
ctor public LocationProviderBase(String, com.android.location.provider.ProviderPropertiesUnbundled);
method public android.os.IBinder getBinder();
- method @RequiresApi(android.os.Build.VERSION_CODES.Q) public boolean isEnabled();
+ method @RequiresApi(android.os.Build.VERSION_CODES.R) public boolean isAllowed();
+ method @Deprecated @RequiresApi(android.os.Build.VERSION_CODES.Q) public boolean isEnabled();
method @Deprecated protected void onDisable();
method @Deprecated protected void onDump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
method @Deprecated protected void onEnable();
method @Deprecated protected int onGetStatus(android.os.Bundle);
method @Deprecated protected long onGetStatusUpdateTime();
method protected void onInit();
+ method protected void onRequestSetAllowed(boolean);
method protected boolean onSendExtraCommand(@Nullable String, @Nullable android.os.Bundle);
method protected abstract void onSetRequest(com.android.location.provider.ProviderRequestUnbundled, android.os.WorkSource);
method public void reportLocation(android.location.Location);
method @RequiresApi(android.os.Build.VERSION_CODES.Q) public void setAdditionalProviderPackages(java.util.List<java.lang.String>);
- method @RequiresApi(android.os.Build.VERSION_CODES.Q) public void setEnabled(boolean);
+ method @RequiresApi(android.os.Build.VERSION_CODES.R) public void setAllowed(boolean);
+ method @Deprecated @RequiresApi(android.os.Build.VERSION_CODES.Q) public void setEnabled(boolean);
method @RequiresApi(android.os.Build.VERSION_CODES.Q) public void setProperties(com.android.location.provider.ProviderPropertiesUnbundled);
field public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
field public static final String FUSED_PROVIDER = "fused";
diff --git a/location/lib/java/com/android/location/provider/LocationProviderBase.java b/location/lib/java/com/android/location/provider/LocationProviderBase.java
index fc7bff3c6dab..f67d08e045e2 100644
--- a/location/lib/java/com/android/location/provider/LocationProviderBase.java
+++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java
@@ -92,7 +92,7 @@ public abstract class LocationProviderBase {
// write locked on mBinder, read lock is optional depending on atomicity requirements
@Nullable private volatile ILocationProviderManager mManager;
private volatile ProviderProperties mProperties;
- private volatile boolean mEnabled;
+ private volatile boolean mAllowed;
private final ArrayList<String> mAdditionalProviderPackages;
public LocationProviderBase(String tag, ProviderPropertiesUnbundled properties) {
@@ -104,7 +104,7 @@ public abstract class LocationProviderBase {
mManager = null;
mProperties = properties.getProviderProperties();
- mEnabled = true;
+ mAllowed = true;
mAdditionalProviderPackages = new ArrayList<>(0);
}
@@ -113,35 +113,44 @@ public abstract class LocationProviderBase {
}
/**
- * Sets whether this provider is currently enabled or not. Note that this is specific to the
+ * @deprecated Use {@link #setAllowed(boolean)} instead.
+ */
+ @Deprecated
+ @RequiresApi(VERSION_CODES.Q)
+ public void setEnabled(boolean enabled) {
+ setAllowed(enabled);
+ }
+
+ /**
+ * Sets whether this provider is currently allowed or not. Note that this is specific to the
* provider only, and is not related to global location settings. This is a hint to the Location
* Manager that this provider will generally be unable to fulfill incoming requests. This
- * provider may still receive callbacks to onSetRequest while not enabled, and must decide
+ * provider may still receive callbacks to onSetRequest while not allowed, and must decide
* whether to attempt to satisfy those requests or not.
*
- * Some guidelines: providers should set their own enabled/disabled status based only on state
- * "owned" by that provider. For instance, providers should not take into account the state of
- * the location master setting when setting themselves enabled or disabled, as this state is not
- * owned by a particular provider. If a provider requires some additional user consent that is
- * particular to the provider, this should be use to set the enabled/disabled state. If the
- * provider proxies to another provider, the child provider's enabled/disabled state should be
- * taken into account in the parent's enabled/disabled state. For most providers, it is expected
- * that they will be always enabled.
+ * <p>Some guidelines: providers should set their own allowed/disallowed status based only on
+ * state "owned" by that provider. For instance, providers should not take into account the
+ * state of the location master setting when setting themselves allowed or disallowed, as this
+ * state is not owned by a particular provider. If a provider requires some additional user
+ * consent that is particular to the provider, this should be use to set the allowed/disallowed
+ * state. If the provider proxies to another provider, the child provider's allowed/disallowed
+ * state should be taken into account in the parent's allowed state. For most providers, it is
+ * expected that they will be always allowed.
*/
- @RequiresApi(VERSION_CODES.Q)
- public void setEnabled(boolean enabled) {
+ @RequiresApi(VERSION_CODES.R)
+ public void setAllowed(boolean allowed) {
synchronized (mBinder) {
- if (mEnabled == enabled) {
+ if (mAllowed == allowed) {
return;
}
- mEnabled = enabled;
+ mAllowed = allowed;
}
ILocationProviderManager manager = mManager;
if (manager != null) {
try {
- manager.onSetEnabled(mEnabled);
+ manager.onSetAllowed(mAllowed);
} catch (RemoteException | RuntimeException e) {
Log.w(mTag, e);
}
@@ -193,12 +202,20 @@ public abstract class LocationProviderBase {
}
/**
- * Returns true if this provider has been set as enabled. This will be true unless explicitly
- * set otherwise.
+ * @deprecated Use {@link #isAllowed()} instead.
*/
+ @Deprecated
@RequiresApi(VERSION_CODES.Q)
public boolean isEnabled() {
- return mEnabled;
+ return isAllowed();
+ }
+
+ /**
+ * Returns true if this provider is allowed. Providers start as allowed on construction.
+ */
+ @RequiresApi(VERSION_CODES.R)
+ public boolean isAllowed() {
+ return mAllowed;
}
/**
@@ -285,6 +302,17 @@ public abstract class LocationProviderBase {
return false;
}
+ /**
+ * Invoked when the system wishes to request that the provider sets its allowed state as
+ * desired. This implies that the caller is providing/retracting consent for any terms and
+ * conditions or consents associated with the provider.
+ *
+ * <p>It is generally only necessary to override this function if the provider has some barriers
+ * or gates for enabling/disabling itself, in which case this function should handle those
+ * appropriately. A provider that is always allowed has no need to override this function.
+ */
+ protected void onRequestSetAllowed(boolean allowed) {}
+
private final class Service extends ILocationProvider.Stub {
@Override
@@ -295,7 +323,7 @@ public abstract class LocationProviderBase {
manager.onSetAdditionalProviderPackages(mAdditionalProviderPackages);
}
manager.onSetProperties(mProperties);
- manager.onSetEnabled(mEnabled);
+ manager.onSetAllowed(mAllowed);
} catch (RemoteException e) {
Log.w(mTag, e);
}
@@ -315,5 +343,10 @@ public abstract class LocationProviderBase {
public void sendExtraCommand(String command, Bundle extras) {
onSendExtraCommand(command, extras);
}
+
+ @Override
+ public void requestSetAllowed(boolean allowed) {
+ onRequestSetAllowed(allowed);
+ }
}
}
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index cbc9683b9cc1..197786f42490 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -763,7 +763,13 @@ public final class MediaCodecInfo {
int maxLevel = 0;
for (CodecProfileLevel pl : profileLevels) {
if (pl.profile == profile && pl.level > maxLevel) {
- maxLevel = pl.level;
+ // H.263 levels are not completely ordered:
+ // Level45 support only implies Level10 support
+ if (!mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)
+ || pl.level != CodecProfileLevel.H263Level45
+ || maxLevel == CodecProfileLevel.H263Level10) {
+ maxLevel = pl.level;
+ }
}
}
levelCaps = createFromProfileLevel(mMime, profile, maxLevel);
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index f408ac344d7c..f61d55ef2a30 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -20,6 +20,8 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
+import android.media.MediaCodec;
+import android.media.MediaParser;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -45,6 +47,7 @@ import java.util.stream.Collectors;
* <table>
* <tr><th>Name</th><th>Value Type</th><th>Description</th></tr>
* <tr><td>{@link #KEY_MIME}</td><td>String</td><td>The type of the format.</td></tr>
+ * <tr><td>{@link #KEY_CODECS_STRING}</td><td>String</td><td>optional, the RFC 6381 codecs string of the MediaFormat</td></tr>
* <tr><td>{@link #KEY_MAX_INPUT_SIZE}</td><td>Integer</td><td>optional, maximum size of a buffer of input data</td></tr>
* <tr><td>{@link #KEY_PIXEL_ASPECT_RATIO_WIDTH}</td><td>Integer</td><td>optional, the pixel aspect ratio width</td></tr>
* <tr><td>{@link #KEY_PIXEL_ASPECT_RATIO_HEIGHT}</td><td>Integer</td><td>optional, the pixel aspect ratio height</td></tr>
@@ -217,6 +220,15 @@ public final class MediaFormat {
public static final String KEY_MIME = "mime";
/**
+ * A key describing the codecs string of the MediaFormat. See RFC 6381 section 3.2 for the
+ * syntax of the value. The value does not hold {@link MediaCodec}-exposed codec names.
+ * The associated value is a string.
+ *
+ * @see MediaParser.TrackData#mediaFormat
+ */
+ public static final String KEY_CODECS_STRING = "codecs-string";
+
+ /**
* An optional key describing the low latency decoding mode. This is an optional parameter
* that applies only to decoders. If enabled, the decoder doesn't hold input and output
* data more than required by the codec standards.
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 4cd581b6628c..1617b875c6f7 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -28,6 +28,7 @@ import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.IBinder;
+import android.text.TextUtils;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -44,6 +45,162 @@ import java.util.Map;
* frame and meta data from an input media file.
*/
public class MediaMetadataRetriever implements AutoCloseable {
+
+ // borrowed from ExoPlayer
+ private static final String[] STANDARD_GENRES = new String[] {
+ // These are the official ID3v1 genres.
+ "Blues",
+ "Classic Rock",
+ "Country",
+ "Dance",
+ "Disco",
+ "Funk",
+ "Grunge",
+ "Hip-Hop",
+ "Jazz",
+ "Metal",
+ "New Age",
+ "Oldies",
+ "Other",
+ "Pop",
+ "R&B",
+ "Rap",
+ "Reggae",
+ "Rock",
+ "Techno",
+ "Industrial",
+ "Alternative",
+ "Ska",
+ "Death Metal",
+ "Pranks",
+ "Soundtrack",
+ "Euro-Techno",
+ "Ambient",
+ "Trip-Hop",
+ "Vocal",
+ "Jazz+Funk",
+ "Fusion",
+ "Trance",
+ "Classical",
+ "Instrumental",
+ "Acid",
+ "House",
+ "Game",
+ "Sound Clip",
+ "Gospel",
+ "Noise",
+ "AlternRock",
+ "Bass",
+ "Soul",
+ "Punk",
+ "Space",
+ "Meditative",
+ "Instrumental Pop",
+ "Instrumental Rock",
+ "Ethnic",
+ "Gothic",
+ "Darkwave",
+ "Techno-Industrial",
+ "Electronic",
+ "Pop-Folk",
+ "Eurodance",
+ "Dream",
+ "Southern Rock",
+ "Comedy",
+ "Cult",
+ "Gangsta",
+ "Top 40",
+ "Christian Rap",
+ "Pop/Funk",
+ "Jungle",
+ "Native American",
+ "Cabaret",
+ "New Wave",
+ "Psychadelic",
+ "Rave",
+ "Showtunes",
+ "Trailer",
+ "Lo-Fi",
+ "Tribal",
+ "Acid Punk",
+ "Acid Jazz",
+ "Polka",
+ "Retro",
+ "Musical",
+ "Rock & Roll",
+ "Hard Rock",
+ // These were made up by the authors of Winamp and later added to the ID3 spec.
+ "Folk",
+ "Folk-Rock",
+ "National Folk",
+ "Swing",
+ "Fast Fusion",
+ "Bebob",
+ "Latin",
+ "Revival",
+ "Celtic",
+ "Bluegrass",
+ "Avantgarde",
+ "Gothic Rock",
+ "Progressive Rock",
+ "Psychedelic Rock",
+ "Symphonic Rock",
+ "Slow Rock",
+ "Big Band",
+ "Chorus",
+ "Easy Listening",
+ "Acoustic",
+ "Humour",
+ "Speech",
+ "Chanson",
+ "Opera",
+ "Chamber Music",
+ "Sonata",
+ "Symphony",
+ "Booty Bass",
+ "Primus",
+ "Porn Groove",
+ "Satire",
+ "Slow Jam",
+ "Club",
+ "Tango",
+ "Samba",
+ "Folklore",
+ "Ballad",
+ "Power Ballad",
+ "Rhythmic Soul",
+ "Freestyle",
+ "Duet",
+ "Punk Rock",
+ "Drum Solo",
+ "A capella",
+ "Euro-House",
+ "Dance Hall",
+ // These were made up by the authors of Winamp but have not been added to the ID3 spec.
+ "Goa",
+ "Drum & Bass",
+ "Club-House",
+ "Hardcore",
+ "Terror",
+ "Indie",
+ "BritPop",
+ "Afro-Punk",
+ "Polsk Punk",
+ "Beat",
+ "Christian Gangsta Rap",
+ "Heavy Metal",
+ "Black Metal",
+ "Crossover",
+ "Contemporary Christian",
+ "Christian Rock",
+ "Merengue",
+ "Salsa",
+ "Thrash Metal",
+ "Anime",
+ "Jpop",
+ "Synthpop"
+ };
+
static {
System.loadLibrary("media_jni");
native_init();
@@ -225,6 +382,8 @@ public class MediaMetadataRetriever implements AutoCloseable {
private native void _setDataSource(MediaDataSource dataSource)
throws IllegalArgumentException;
+ private native @Nullable String nativeExtractMetadata(int keyCode);
+
/**
* Call this method after setDataSource(). This method retrieves the
* meta data value associated with the keyCode.
@@ -236,7 +395,118 @@ public class MediaMetadataRetriever implements AutoCloseable {
* @return The meta data value associate with the given keyCode on success;
* null on failure.
*/
- public native @Nullable String extractMetadata(int keyCode);
+ public @Nullable String extractMetadata(int keyCode) {
+ String meta = nativeExtractMetadata(keyCode);
+ if (keyCode == METADATA_KEY_GENRE) {
+ // translate numeric genre code(s) to human readable
+ meta = convertGenreTag(meta);
+ }
+ return meta;
+ }
+
+ /*
+ * The id3v2 spec doesn't specify the syntax of the genre tag very precisely, so
+ * some assumptions are made. Using one possible interpretation of the id3v2
+ * spec, this method converts an id3 genre tag string to a human readable string,
+ * as follows:
+ * - if the first character of the tag is a digit, the entire tag is assumed to
+ * be an id3v1 numeric genre code. If the tag does not parse to a number, or
+ * the number is outside the range of defined standard genres, it is ignored.
+ * - if the tag does not start with a digit, it is assumed to be an id3v2 style
+ * tag consisting of one or more genres, with each genre being either a parenthesized
+ * integer referring to an id3v1 numeric genre code, the special indicators "(CR)" or
+ * "(RX)" (for "Cover" or "Remix", respectively), or a custom genre string. When
+ * a custom genre string is encountered, it is assumed to continue until the end
+ * of the tag, unless it starts with "((" in which case it is assumed to continue
+ * until the next close-parenthesis or the end of the tag. Any parse error in the tag
+ * causes it to be ignored.
+ * The human-readable genre string is not localized, and uses the English genre names
+ * from the spec.
+ */
+ private String convertGenreTag(String meta) {
+ if (TextUtils.isEmpty(meta)) {
+ return null;
+ }
+
+ if (Character.isDigit(meta.charAt(0))) {
+ // assume a single id3v1-style bare number without any extra characters
+ try {
+ int genreIndex = Integer.parseInt(meta);
+ if (genreIndex >= 0 && genreIndex < STANDARD_GENRES.length) {
+ return STANDARD_GENRES[genreIndex];
+ }
+ } catch (NumberFormatException e) {
+ // ignore and fall through
+ }
+ return null;
+ } else {
+ // assume id3v2-style genre tag, with parenthesized numeric genres
+ // and/or literal genre strings, possibly more than one per tag.
+ StringBuilder genres = null;
+ String nextGenre = null;
+ while (true) {
+ if (!TextUtils.isEmpty(nextGenre)) {
+ if (genres == null) {
+ genres = new StringBuilder();
+ }
+ if (genres.length() != 0) {
+ genres.append(", ");
+ }
+ genres.append(nextGenre);
+ nextGenre = null;
+ }
+ if (TextUtils.isEmpty(meta)) {
+ // entire tag has been processed.
+ break;
+ }
+ if (meta.startsWith("(RX)")) {
+ nextGenre = "Remix";
+ meta = meta.substring(4);
+ } else if (meta.startsWith("(CR)")) {
+ nextGenre = "Cover";
+ meta = meta.substring(4);
+ } else if (meta.startsWith("((")) {
+ // the id3v2 spec says that custom genres that start with a parenthesis
+ // should be "escaped" with another parenthesis, however the spec doesn't
+ // specify escaping parentheses inside the custom string. We'll parse any
+ // such strings until a closing parenthesis is found, or the end of
+ // the tag is reached.
+ int closeParenOffset = meta.indexOf(')');
+ if (closeParenOffset == -1) {
+ // string continues to end of tag
+ nextGenre = meta.substring(1);
+ meta = "";
+ } else {
+ nextGenre = meta.substring(1, closeParenOffset + 1);
+ meta = meta.substring(closeParenOffset + 1);
+ }
+ } else if (meta.startsWith("(")) {
+ // should be a parenthesized numeric genre
+ int closeParenOffset = meta.indexOf(')');
+ if (closeParenOffset == -1) {
+ return null;
+ }
+ String genreNumString = meta.substring(1, closeParenOffset);
+ try {
+ int genreIndex = Integer.parseInt(genreNumString.toString());
+ if (genreIndex >= 0 && genreIndex < STANDARD_GENRES.length) {
+ nextGenre = STANDARD_GENRES[genreIndex];
+ } else {
+ return null;
+ }
+ } catch (NumberFormatException e) {
+ return null;
+ }
+ meta = meta.substring(closeParenOffset + 1);
+ } else {
+ // custom genre
+ nextGenre = meta;
+ meta = "";
+ }
+ }
+ return genres == null || genres.length() == 0 ? null : genres.toString();
+ }
+ }
/**
* This method is similar to {@link #getFrameAtTime(long, int, BitmapParams)}
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index ab6966d5d1c3..9b37f955fa17 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -1750,22 +1750,150 @@ static void android_media_MediaCodec_queueSecureInputBuffer(
return;
}
- NativeCryptoInfo cryptoInfo{env, cryptoInfoObj};
+ jint numSubSamples =
+ env->GetIntField(cryptoInfoObj, gFields.cryptoInfoNumSubSamplesID);
+
+ jintArray numBytesOfClearDataObj =
+ (jintArray)env->GetObjectField(
+ cryptoInfoObj, gFields.cryptoInfoNumBytesOfClearDataID);
+
+ jintArray numBytesOfEncryptedDataObj =
+ (jintArray)env->GetObjectField(
+ cryptoInfoObj, gFields.cryptoInfoNumBytesOfEncryptedDataID);
+
+ jbyteArray keyObj =
+ (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoKeyID);
+
+ jbyteArray ivObj =
+ (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID);
+
+ jint jmode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID);
+ enum CryptoPlugin::Mode mode;
+ if (jmode == gCryptoModes.Unencrypted) {
+ mode = CryptoPlugin::kMode_Unencrypted;
+ } else if (jmode == gCryptoModes.AesCtr) {
+ mode = CryptoPlugin::kMode_AES_CTR;
+ } else if (jmode == gCryptoModes.AesCbc) {
+ mode = CryptoPlugin::kMode_AES_CBC;
+ } else {
+ throwExceptionAsNecessary(env, INVALID_OPERATION);
+ return;
+ }
+
+ jobject patternObj = env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoPatternID);
+
+ CryptoPlugin::Pattern pattern;
+ if (patternObj == NULL) {
+ pattern.mEncryptBlocks = 0;
+ pattern.mSkipBlocks = 0;
+ } else {
+ pattern.mEncryptBlocks = env->GetIntField(patternObj, gFields.patternEncryptBlocksID);
+ pattern.mSkipBlocks = env->GetIntField(patternObj, gFields.patternSkipBlocksID);
+ }
+
+ status_t err = OK;
+
+ CryptoPlugin::SubSample *subSamples = NULL;
+ jbyte *key = NULL;
+ jbyte *iv = NULL;
+
+ if (numSubSamples <= 0) {
+ err = -EINVAL;
+ } else if (numBytesOfClearDataObj == NULL
+ && numBytesOfEncryptedDataObj == NULL) {
+ err = -EINVAL;
+ } else if (numBytesOfEncryptedDataObj != NULL
+ && env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) {
+ err = -ERANGE;
+ } else if (numBytesOfClearDataObj != NULL
+ && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
+ err = -ERANGE;
+ // subSamples array may silently overflow if number of samples are too large. Use
+ // INT32_MAX as maximum allocation size may be less than SIZE_MAX on some platforms
+ } else if ( CC_UNLIKELY(numSubSamples >= (signed)(INT32_MAX / sizeof(*subSamples))) ) {
+ err = -EINVAL;
+ } else {
+ jboolean isCopy;
+
+ jint *numBytesOfClearData =
+ (numBytesOfClearDataObj == NULL)
+ ? NULL
+ : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
+
+ jint *numBytesOfEncryptedData =
+ (numBytesOfEncryptedDataObj == NULL)
+ ? NULL
+ : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
+
+ subSamples = new CryptoPlugin::SubSample[numSubSamples];
+
+ for (jint i = 0; i < numSubSamples; ++i) {
+ subSamples[i].mNumBytesOfClearData =
+ (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
+
+ subSamples[i].mNumBytesOfEncryptedData =
+ (numBytesOfEncryptedData == NULL)
+ ? 0 : numBytesOfEncryptedData[i];
+ }
+
+ if (numBytesOfEncryptedData != NULL) {
+ env->ReleaseIntArrayElements(
+ numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
+ numBytesOfEncryptedData = NULL;
+ }
+
+ if (numBytesOfClearData != NULL) {
+ env->ReleaseIntArrayElements(
+ numBytesOfClearDataObj, numBytesOfClearData, 0);
+ numBytesOfClearData = NULL;
+ }
+ }
+
+ if (err == OK && keyObj != NULL) {
+ if (env->GetArrayLength(keyObj) != 16) {
+ err = -EINVAL;
+ } else {
+ jboolean isCopy;
+ key = env->GetByteArrayElements(keyObj, &isCopy);
+ }
+ }
+
+ if (err == OK && ivObj != NULL) {
+ if (env->GetArrayLength(ivObj) != 16) {
+ err = -EINVAL;
+ } else {
+ jboolean isCopy;
+ iv = env->GetByteArrayElements(ivObj, &isCopy);
+ }
+ }
+
AString errorDetailMsg;
- status_t err = cryptoInfo.mErr;
if (err == OK) {
err = codec->queueSecureInputBuffer(
index, offset,
- cryptoInfo.mSubSamples, cryptoInfo.mNumSubSamples,
- (const uint8_t *)cryptoInfo.mKey, (const uint8_t *)cryptoInfo.mIv,
- cryptoInfo.mMode,
- cryptoInfo.mPattern,
+ subSamples, numSubSamples,
+ (const uint8_t *)key, (const uint8_t *)iv,
+ mode,
+ pattern,
timestampUs,
flags,
&errorDetailMsg);
}
+ if (iv != NULL) {
+ env->ReleaseByteArrayElements(ivObj, iv, 0);
+ iv = NULL;
+ }
+
+ if (key != NULL) {
+ env->ReleaseByteArrayElements(keyObj, key, 0);
+ key = NULL;
+ }
+
+ delete[] subSamples;
+ subSamples = NULL;
+
throwExceptionAsNecessary(
env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
}
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index a5c62cb720cf..1c9b349a7eed 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -728,7 +728,7 @@ static const JNINativeMethod nativeMethods[] = {
(void *)android_media_MediaMetadataRetriever_getFrameAtIndex
},
- {"extractMetadata", "(I)Ljava/lang/String;",
+ {"nativeExtractMetadata", "(I)Ljava/lang/String;",
(void *)android_media_MediaMetadataRetriever_extractMetadata},
{"getEmbeddedPicture", "(I)[B",
(void *)android_media_MediaMetadataRetriever_getEmbeddedPicture},
diff --git a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
index 33126510bc53..d1a379afa25e 100644
--- a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
+++ b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
@@ -205,7 +205,7 @@ public class FusedLocationServiceTest {
}
@Override
- public void onSetEnabled(boolean enabled) {
+ public void onSetAllowed(boolean allowed) {
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 486386f3d284..107207638205 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -4488,7 +4488,7 @@ public class SettingsProvider extends ContentProvider {
try {
overlayManager.setEnabledExclusiveInCategory(
NAV_BAR_MODE_2BUTTON_OVERLAY, UserHandle.USER_CURRENT);
- } catch (RemoteException e) {
+ } catch (SecurityException | IllegalStateException | RemoteException e) {
throw new IllegalStateException(
"Failed to set nav bar interaction mode overlay");
}
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index b896a2a8d9a4..fa2e36538dc3 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -574,7 +574,8 @@ public class SettingsBackupTest {
Settings.Global.ENABLED_SUBSCRIPTION_FOR_SLOT,
Settings.Global.MODEM_STACK_ENABLED_FOR_SLOT,
Settings.Global.POWER_BUTTON_LONG_PRESS,
- Settings.Global.POWER_BUTTON_VERY_LONG_PRESS);
+ Settings.Global.POWER_BUTTON_VERY_LONG_PRESS,
+ Settings.Global.INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER);
private static final Set<String> BACKUP_BLACKLISTED_SECURE_SETTINGS =
newHashSet(
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index e52010600ab3..edcd8012c82c 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -296,6 +296,7 @@
<item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
<item>com.android.systemui.theme.ThemeOverlayController</item>
<item>com.android.systemui.accessibility.WindowMagnification</item>
+ <item>com.android.systemui.accessibility.SystemActions</item>
</string-array>
<!-- SystemUI vender service, used in config_systemUIServiceComponents. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 65ca9f2132cd..b40c5c0b0264 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -96,6 +96,9 @@
<!-- Spacing before the airplane mode icon if there are any icons preceding it. -->
<dimen name="status_bar_airplane_spacer_width">4dp</dimen>
+ <!-- Spacing between system icons. -->
+ <dimen name="status_bar_system_icon_spacing">0dp</dimen>
+
<!-- The amount to scale each of the status bar icons by. A value of 1 means no scaling. -->
<item name="status_bar_icon_scale_factor" format="float" type="dimen">1.0</item>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
index 98b7e2484478..44a8d3c53db7 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
@@ -16,6 +16,7 @@
package com.android.systemui.shared.recents.model;
+import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_UNDEFINED;
@@ -31,6 +32,7 @@ public class ThumbnailData {
public final Bitmap thumbnail;
public int orientation;
+ public int rotation;
public Rect insets;
public boolean reducedResolution;
public boolean isRealSnapshot;
@@ -43,6 +45,7 @@ public class ThumbnailData {
public ThumbnailData() {
thumbnail = null;
orientation = ORIENTATION_UNDEFINED;
+ rotation = ROTATION_UNDEFINED;
insets = new Rect();
reducedResolution = false;
scale = 1f;
@@ -57,6 +60,7 @@ public class ThumbnailData {
thumbnail = Bitmap.wrapHardwareBuffer(snapshot.getSnapshot(), snapshot.getColorSpace());
insets = new Rect(snapshot.getContentInsets());
orientation = snapshot.getOrientation();
+ rotation = snapshot.getRotation();
reducedResolution = snapshot.isReducedResolution();
scale = snapshot.getScale();
isRealSnapshot = snapshot.isRealSnapshot();
diff --git a/packages/SystemUI/src/com/android/systemui/DumpController.kt b/packages/SystemUI/src/com/android/systemui/DumpController.kt
index f14c4cd8e6c6..7a83a8948bb0 100644
--- a/packages/SystemUI/src/com/android/systemui/DumpController.kt
+++ b/packages/SystemUI/src/com/android/systemui/DumpController.kt
@@ -19,10 +19,10 @@ package com.android.systemui
import android.util.ArraySet
import android.util.Log
import androidx.annotation.GuardedBy
-import com.android.internal.util.Preconditions
import java.io.FileDescriptor
import java.io.PrintWriter
import java.lang.ref.WeakReference
+import java.util.Objects.requireNonNull
import javax.inject.Inject
import javax.inject.Singleton
@@ -58,7 +58,7 @@ class DumpController @Inject constructor() : Dumpable {
* @param dumpable the [Dumpable] to be added
*/
fun registerDumpable(dumpable: Dumpable) {
- Preconditions.checkNotNull(dumpable, "The dumpable to be added cannot be null")
+ requireNonNull(dumpable, "The dumpable to be added cannot be null")
registerDumpable(dumpable.javaClass.simpleName, dumpable)
}
@@ -71,7 +71,7 @@ class DumpController @Inject constructor() : Dumpable {
* @param dumpable the [Dumpable] to be added
*/
fun registerDumpable(tag: String, dumpable: Dumpable) {
- Preconditions.checkNotNull(dumpable, "The dumpable to be added cannot be null")
+ requireNonNull(dumpable, "The dumpable to be added cannot be null")
if (DEBUG) Log.v(TAG, "*** register callback for $dumpable")
synchronized<Unit>(listeners) {
if (listeners.any { it.tag == tag }) {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
new file mode 100644
index 000000000000..7262f8caac89
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2020 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.systemui.accessibility;
+
+import android.accessibilityservice.AccessibilityService;
+import android.app.PendingIntent;
+import android.app.RemoteAction;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.drawable.Icon;
+import android.hardware.input.InputManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.Display;
+import android.view.IWindowManager;
+import android.view.InputDevice;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.internal.R;
+import com.android.internal.util.ScreenshotHelper;
+import com.android.systemui.Dependency;
+import com.android.systemui.SystemUI;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Class to register system actions with accessibility framework.
+ */
+@Singleton
+public class SystemActions extends SystemUI {
+ private static final String TAG = "SystemActions";
+ // TODO(b/147916452): add implementation on launcher side to register this action.
+
+ /**
+ * Action ID to go back.
+ */
+ private static final int SYSTEM_ACTION_ID_BACK = AccessibilityService.GLOBAL_ACTION_BACK; // = 1
+
+ /**
+ * Action ID to go home.
+ */
+ private static final int SYSTEM_ACTION_ID_HOME = AccessibilityService.GLOBAL_ACTION_HOME; // = 2
+
+ /**
+ * Action ID to toggle showing the overview of recent apps. Will fail on platforms that don't
+ * show recent apps.
+ */
+ private static final int SYSTEM_ACTION_ID_RECENTS =
+ AccessibilityService.GLOBAL_ACTION_RECENTS; // = 3
+
+ /**
+ * Action ID to open the notifications.
+ */
+ private static final int SYSTEM_ACTION_ID_NOTIFICATIONS =
+ AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS; // = 4
+
+ /**
+ * Action ID to open the quick settings.
+ */
+ private static final int SYSTEM_ACTION_ID_QUICK_SETTINGS =
+ AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS; // = 5
+
+ /**
+ * Action ID to open the power long-press dialog.
+ */
+ private static final int SYSTEM_ACTION_ID_POWER_DIALOG =
+ AccessibilityService.GLOBAL_ACTION_POWER_DIALOG; // = 6
+
+ /**
+ * Action ID to toggle docking the current app's window
+ */
+ private static final int SYSTEM_ACTION_ID_TOGGLE_SPLIT_SCREEN =
+ AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN; // = 7
+
+ /**
+ * Action ID to lock the screen
+ */
+ private static final int SYSTEM_ACTION_ID_LOCK_SCREEN =
+ AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN; // = 8
+
+ /**
+ * Action ID to take a screenshot
+ */
+ private static final int SYSTEM_ACTION_ID_TAKE_SCREENSHOT =
+ AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT; // = 9
+
+ /**
+ * Action ID to show accessibility menu
+ */
+ private static final int SYSTEM_ACTION_ID_ACCESSIBILITY_MENU = 10;
+
+ private Recents mRecents;
+ private StatusBar mStatusBar;
+ private SystemActionsBroadcastReceiver mReceiver;
+
+ @Inject
+ public SystemActions(Context context) {
+ super(context);
+ mRecents = Dependency.get(Recents.class);
+ mStatusBar = Dependency.get(StatusBar.class);
+ mReceiver = new SystemActionsBroadcastReceiver();
+ }
+
+ @Override
+ public void start() {
+ mContext.registerReceiverForAllUsers(mReceiver, mReceiver.createIntentFilter(), null, null);
+
+ // TODO(b/148087487): update the icon used below to a valid one
+ RemoteAction actionBack = new RemoteAction(
+ Icon.createWithResource(mContext, R.drawable.ic_info),
+ mContext.getString(R.string.accessibility_system_action_back_label),
+ mContext.getString(R.string.accessibility_system_action_back_label),
+ mReceiver.createPendingIntent(
+ mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_BACK));
+ RemoteAction actionHome = new RemoteAction(
+ Icon.createWithResource(mContext, R.drawable.ic_info),
+ mContext.getString(R.string.accessibility_system_action_home_label),
+ mContext.getString(R.string.accessibility_system_action_home_label),
+ mReceiver.createPendingIntent(
+ mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_HOME));
+
+ RemoteAction actionRecents = new RemoteAction(
+ Icon.createWithResource(mContext, R.drawable.ic_info),
+ mContext.getString(R.string.accessibility_system_action_recents_label),
+ mContext.getString(R.string.accessibility_system_action_recents_label),
+ mReceiver.createPendingIntent(
+ mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_RECENTS));
+
+ RemoteAction actionNotifications = new RemoteAction(
+ Icon.createWithResource(mContext, R.drawable.ic_info),
+ mContext.getString(R.string.accessibility_system_action_notifications_label),
+ mContext.getString(R.string.accessibility_system_action_notifications_label),
+ mReceiver.createPendingIntent(
+ mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_NOTIFICATIONS));
+
+ RemoteAction actionQuickSettings = new RemoteAction(
+ Icon.createWithResource(mContext, R.drawable.ic_info),
+ mContext.getString(R.string.accessibility_system_action_quick_settings_label),
+ mContext.getString(R.string.accessibility_system_action_quick_settings_label),
+ mReceiver.createPendingIntent(
+ mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_QUICK_SETTINGS));
+
+ RemoteAction actionPowerDialog = new RemoteAction(
+ Icon.createWithResource(mContext, R.drawable.ic_info),
+ mContext.getString(R.string.accessibility_system_action_power_dialog_label),
+ mContext.getString(R.string.accessibility_system_action_power_dialog_label),
+ mReceiver.createPendingIntent(
+ mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_POWER_DIALOG));
+
+ RemoteAction actionToggleSplitScreen = new RemoteAction(
+ Icon.createWithResource(mContext, R.drawable.ic_info),
+ mContext.getString(R.string.accessibility_system_action_toggle_split_screen_label),
+ mContext.getString(R.string.accessibility_system_action_toggle_split_screen_label),
+ mReceiver.createPendingIntent(
+ mContext,
+ SystemActionsBroadcastReceiver.INTENT_ACTION_TOGGLE_SPLIT_SCREEN));
+
+ RemoteAction actionLockScreen = new RemoteAction(
+ Icon.createWithResource(mContext, R.drawable.ic_info),
+ mContext.getString(R.string.accessibility_system_action_lock_screen_label),
+ mContext.getString(R.string.accessibility_system_action_lock_screen_label),
+ mReceiver.createPendingIntent(
+ mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_LOCK_SCREEN));
+
+ RemoteAction actionTakeScreenshot = new RemoteAction(
+ Icon.createWithResource(mContext, R.drawable.ic_info),
+ mContext.getString(R.string.accessibility_system_action_screenshot_label),
+ mContext.getString(R.string.accessibility_system_action_screenshot_label),
+ mReceiver.createPendingIntent(
+ mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_TAKE_SCREENSHOT));
+
+ RemoteAction actionAccessibilityMenu = new RemoteAction(
+ Icon.createWithResource(mContext, R.drawable.ic_info),
+ mContext.getString(R.string.accessibility_system_action_accessibility_menu_label),
+ mContext.getString(R.string.accessibility_system_action_accessibility_menu_label),
+ mReceiver.createPendingIntent(
+ mContext, SystemActionsBroadcastReceiver.INTENT_ACTION_ACCESSIBILITY_MENU));
+
+ AccessibilityManager am = (AccessibilityManager) mContext.getSystemService(
+ Context.ACCESSIBILITY_SERVICE);
+
+ am.registerSystemAction(actionBack, SYSTEM_ACTION_ID_BACK);
+ am.registerSystemAction(actionHome, SYSTEM_ACTION_ID_HOME);
+ am.registerSystemAction(actionRecents, SYSTEM_ACTION_ID_RECENTS);
+ am.registerSystemAction(actionNotifications, SYSTEM_ACTION_ID_NOTIFICATIONS);
+ am.registerSystemAction(actionQuickSettings, SYSTEM_ACTION_ID_QUICK_SETTINGS);
+ am.registerSystemAction(actionPowerDialog, SYSTEM_ACTION_ID_POWER_DIALOG);
+ am.registerSystemAction(actionToggleSplitScreen, SYSTEM_ACTION_ID_TOGGLE_SPLIT_SCREEN);
+ am.registerSystemAction(actionLockScreen, SYSTEM_ACTION_ID_LOCK_SCREEN);
+ am.registerSystemAction(actionTakeScreenshot, SYSTEM_ACTION_ID_TAKE_SCREENSHOT);
+ am.registerSystemAction(actionAccessibilityMenu, SYSTEM_ACTION_ID_ACCESSIBILITY_MENU);
+ }
+
+ private void handleBack() {
+ sendDownAndUpKeyEvents(KeyEvent.KEYCODE_BACK);
+ }
+
+ private void handleHome() {
+ sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HOME);
+ }
+
+ private void sendDownAndUpKeyEvents(int keyCode) {
+ final long downTime = SystemClock.uptimeMillis();
+ sendKeyEventIdentityCleared(keyCode, KeyEvent.ACTION_DOWN, downTime, downTime);
+ sendKeyEventIdentityCleared(
+ keyCode, KeyEvent.ACTION_UP, downTime, SystemClock.uptimeMillis());
+ }
+
+ private void sendKeyEventIdentityCleared(int keyCode, int action, long downTime, long time) {
+ KeyEvent event = KeyEvent.obtain(downTime, time, action, keyCode, 0, 0,
+ KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
+ InputDevice.SOURCE_KEYBOARD, null);
+ InputManager.getInstance()
+ .injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+ event.recycle();
+ }
+
+ private void handleRecents() {
+ mRecents.toggleRecentApps();
+ }
+
+ private void handleNotifications() {
+ mStatusBar.animateExpandNotificationsPanel();
+ }
+
+ private void handleQuickSettings() {
+ mStatusBar.animateExpandSettingsPanel(null);
+ }
+
+ private void handlePowerDialog() {
+ IWindowManager windowManager = WindowManagerGlobal.getWindowManagerService();
+
+ try {
+ windowManager.showGlobalActions();
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to display power dialog.");
+ }
+ }
+
+ private void handleToggleSplitScreen() {
+ mStatusBar.toggleSplitScreen();
+ }
+
+ private void handleLockScreen() {
+ IWindowManager windowManager = WindowManagerGlobal.getWindowManagerService();
+
+ mContext.getSystemService(PowerManager.class).goToSleep(SystemClock.uptimeMillis(),
+ PowerManager.GO_TO_SLEEP_REASON_ACCESSIBILITY, 0);
+ try {
+ windowManager.lockNow(null);
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to lock screen.");
+ }
+ }
+
+ private void handleTakeScreenshot() {
+ ScreenshotHelper screenshotHelper = new ScreenshotHelper(mContext);
+ screenshotHelper.takeScreenshot(WindowManager.TAKE_SCREENSHOT_FULLSCREEN,
+ true, true, new Handler(Looper.getMainLooper()), null);
+ }
+
+ private void handleAccessibilityMenu() {
+ AccessibilityManager.getInstance(mContext).notifyAccessibilityButtonClicked(
+ Display.DEFAULT_DISPLAY);
+ }
+
+ private class SystemActionsBroadcastReceiver extends BroadcastReceiver {
+ private static final String INTENT_ACTION_BACK = "SYSTEM_ACTION_BACK";
+ private static final String INTENT_ACTION_HOME = "SYSTEM_ACTION_HOME";
+ private static final String INTENT_ACTION_RECENTS = "SYSTEM_ACTION_RECENTS";
+ private static final String INTENT_ACTION_NOTIFICATIONS = "SYSTEM_ACTION_NOTIFICATIONS";
+ private static final String INTENT_ACTION_QUICK_SETTINGS = "SYSTEM_ACTION_QUICK_SETTINGS";
+ private static final String INTENT_ACTION_POWER_DIALOG = "SYSTEM_ACTION_POWER_DIALOG";
+ private static final String INTENT_ACTION_TOGGLE_SPLIT_SCREEN =
+ "SYSTEM_ACTION_TOGGLE_SPLIT_SCREEN";
+ private static final String INTENT_ACTION_LOCK_SCREEN = "SYSTEM_ACTION_LOCK_SCREEN";
+ private static final String INTENT_ACTION_TAKE_SCREENSHOT = "SYSTEM_ACTION_TAKE_SCREENSHOT";
+ private static final String INTENT_ACTION_ACCESSIBILITY_MENU =
+ "SYSTEM_ACTION_ACCESSIBILITY_MENU";
+
+ private PendingIntent createPendingIntent(Context context, String intentAction) {
+ switch (intentAction) {
+ case INTENT_ACTION_BACK:
+ case INTENT_ACTION_HOME:
+ case INTENT_ACTION_RECENTS:
+ case INTENT_ACTION_NOTIFICATIONS:
+ case INTENT_ACTION_QUICK_SETTINGS:
+ case INTENT_ACTION_POWER_DIALOG:
+ case INTENT_ACTION_TOGGLE_SPLIT_SCREEN:
+ case INTENT_ACTION_LOCK_SCREEN:
+ case INTENT_ACTION_TAKE_SCREENSHOT:
+ case INTENT_ACTION_ACCESSIBILITY_MENU: {
+ Intent intent = new Intent(intentAction);
+ return PendingIntent.getBroadcast(context, 0, intent, 0);
+ }
+ default:
+ break;
+ }
+ return null;
+ }
+
+ private IntentFilter createIntentFilter() {
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(INTENT_ACTION_BACK);
+ intentFilter.addAction(INTENT_ACTION_HOME);
+ intentFilter.addAction(INTENT_ACTION_RECENTS);
+ intentFilter.addAction(INTENT_ACTION_NOTIFICATIONS);
+ intentFilter.addAction(INTENT_ACTION_QUICK_SETTINGS);
+ intentFilter.addAction(INTENT_ACTION_POWER_DIALOG);
+ intentFilter.addAction(INTENT_ACTION_TOGGLE_SPLIT_SCREEN);
+ intentFilter.addAction(INTENT_ACTION_LOCK_SCREEN);
+ intentFilter.addAction(INTENT_ACTION_TAKE_SCREENSHOT);
+ intentFilter.addAction(INTENT_ACTION_ACCESSIBILITY_MENU);
+ return intentFilter;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String intentAction = intent.getAction();
+ switch (intentAction) {
+ case INTENT_ACTION_BACK: {
+ handleBack();
+ break;
+ }
+ case INTENT_ACTION_HOME: {
+ handleHome();
+ break;
+ }
+ case INTENT_ACTION_RECENTS: {
+ handleRecents();
+ break;
+ }
+ case INTENT_ACTION_NOTIFICATIONS: {
+ handleNotifications();
+ break;
+ }
+ case INTENT_ACTION_QUICK_SETTINGS: {
+ handleQuickSettings();
+ break;
+ }
+ case INTENT_ACTION_POWER_DIALOG: {
+ handlePowerDialog();
+ break;
+ }
+ case INTENT_ACTION_TOGGLE_SPLIT_SCREEN: {
+ handleToggleSplitScreen();
+ break;
+ }
+ case INTENT_ACTION_LOCK_SCREEN: {
+ handleLockScreen();
+ break;
+ }
+ case INTENT_ACTION_TAKE_SCREENSHOT: {
+ handleTakeScreenshot();
+ break;
+ }
+ case INTENT_ACTION_ACCESSIBILITY_MENU: {
+ handleAccessibilityMenu();
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
index 99dd5e2356d6..d4e47f699345 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
@@ -21,6 +21,7 @@ import com.android.systemui.ScreenDecorations;
import com.android.systemui.SizeCompatModeActivityController;
import com.android.systemui.SliceBroadcastRelayHandler;
import com.android.systemui.SystemUI;
+import com.android.systemui.accessibility.SystemActions;
import com.android.systemui.accessibility.WindowMagnification;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.globalactions.GlobalActionsComponent;
@@ -140,6 +141,12 @@ public abstract class SystemUIBinder {
@ClassKey(StatusBar.class)
public abstract SystemUI bindsStatusBar(StatusBar sysui);
+ /** Inject into SystemActions. */
+ @Binds
+ @IntoMap
+ @ClassKey(SystemActions.class)
+ public abstract SystemUI bindSystemActions(SystemActions sysui);
+
/** Inject into ThemeOverlayController. */
@Binds
@IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
index d6336ed3e18a..826af669cb39 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
@@ -387,7 +387,7 @@ public class NavigationModeController implements Dumpable {
Log.d(TAG, "setModeOverlay: overlayPackage=" + overlayPkg
+ " userId=" + userId);
}
- } catch (RemoteException e) {
+ } catch (SecurityException | IllegalStateException | RemoteException e) {
Log.e(TAG, "Failed to enable overlay " + overlayPkg + " for user " + userId);
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
index d06164963f7b..5a7c5c9b5ebc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -56,6 +56,7 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
private static final int MAX_DOTS = 1;
private int mDotPadding;
+ private int mIconSpacing;
private int mStaticDotDiameter;
private int mUnderflowWidth;
private int mUnderflowStart = 0;
@@ -99,6 +100,7 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
mIconDotFrameWidth = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_icon_size);
mDotPadding = getResources().getDimensionPixelSize(R.dimen.overflow_icon_dot_padding);
+ mIconSpacing = getResources().getDimensionPixelSize(R.dimen.status_bar_system_icon_spacing);
int radius = getResources().getDimensionPixelSize(R.dimen.overflow_dot_radius);
mStaticDotDiameter = 2 * radius;
mUnderflowWidth = mIconDotFrameWidth + (MAX_DOTS - 1) * (mStaticDotDiameter + mDotPadding);
@@ -163,20 +165,21 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
// Measure all children so that they report the correct width
int childWidthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED);
mNeedsUnderflow = mShouldRestrictIcons && visibleCount > MAX_ICONS;
- for (int i = 0; i < mMeasureViews.size(); i++) {
+ for (int i = 0; i < visibleCount; i++) {
// Walking backwards
View child = mMeasureViews.get(visibleCount - i - 1);
measureChild(child, childWidthSpec, heightMeasureSpec);
+ int spacing = i == visibleCount - 1 ? 0 : mIconSpacing;
if (mShouldRestrictIcons) {
if (i < maxVisible && trackWidth) {
- totalWidth += getViewTotalMeasuredWidth(child);
+ totalWidth += getViewTotalMeasuredWidth(child) + spacing;
} else if (trackWidth) {
// We've hit the icon limit; add space for dots
totalWidth += mUnderflowWidth;
trackWidth = false;
}
} else {
- totalWidth += getViewTotalMeasuredWidth(child);
+ totalWidth += getViewTotalMeasuredWidth(child) + spacing;
}
}
@@ -284,11 +287,15 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
continue;
}
+ // Move translationX to the spot within StatusIconContainer's layout to add the view
+ // without cutting off the child view.
+ translationX -= getViewTotalWidth(child);
childState.visibleState = STATE_ICON;
- childState.xTranslation = translationX - getViewTotalWidth(child);
+ childState.xTranslation = translationX;
mLayoutStates.add(0, childState);
- translationX -= getViewTotalWidth(child);
+ // Shift translationX over by mIconSpacing for the next view.
+ translationX -= mIconSpacing;
}
// Show either 1-MAX_ICONS icons, or (MAX_ICONS - 1) icons + overflow
@@ -306,7 +313,8 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
firstUnderflowIndex = i;
break;
}
- mUnderflowStart = (int) Math.max(contentStart, state.xTranslation - mUnderflowWidth);
+ mUnderflowStart = (int) Math.max(
+ contentStart, state.xTranslation - mUnderflowWidth - mIconSpacing);
visible++;
}
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java
index 41e026af7c72..665cb6307b6a 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayManager.java
@@ -178,7 +178,7 @@ class ThemeOverlayManager {
} else {
mOverlayManager.setEnabled(pkg, false, userHandle);
}
- } catch (IllegalStateException e) {
+ } catch (SecurityException | IllegalStateException e) {
Log.e(TAG,
String.format("setEnabled failed: %s %s %b", pkg, userHandle, enabled), e);
}
diff --git a/proto/src/task_snapshot.proto b/proto/src/task_snapshot.proto
index 821db860dd96..789019ce8b75 100644
--- a/proto/src/task_snapshot.proto
+++ b/proto/src/task_snapshot.proto
@@ -34,4 +34,5 @@
string top_activity_component = 10;
float scale = 11;
int64 id = 12;
+ int32 rotation = 13;
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 26245b15f92b..28298cb51f6e 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -634,8 +634,11 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
final SuspendDialogInfo dialogInfo =
mPackageManagerInternal.getSuspendedDialogInfo(providerPackage,
suspendingPackage, providerUserId);
+ // TODO(b/148035643): Send the original widget intent or ACTION_MAIN as an
+ // IntentSender to SuspendedAppActivity.
onClickIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent(
- providerPackage, suspendingPackage, dialogInfo, null, providerUserId);
+ providerPackage, suspendingPackage, dialogInfo, null, null,
+ providerUserId);
}
} else if (provider.maskedByQuietProfile) {
showBadge = true;
diff --git a/services/core/java/android/app/usage/UsageStatsManagerInternal.java b/services/core/java/android/app/usage/UsageStatsManagerInternal.java
index f3647602e69b..a8be66990fff 100644
--- a/services/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/services/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -16,10 +16,14 @@
package android.app.usage;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.usage.UsageStatsManager.StandbyBuckets;
import android.content.ComponentName;
+import android.content.LocusId;
import android.content.res.Configuration;
+import android.os.IBinder;
import android.os.UserHandle;
import android.os.UserManager;
@@ -111,6 +115,20 @@ public abstract class UsageStatsManagerInternal {
public abstract void reportContentProviderUsage(String name, String pkgName,
@UserIdInt int userId);
+
+ /**
+ * Reports locusId update for a given activity.
+ *
+ * @param activity The component name of the app.
+ * @param userId The user id of who uses the app.
+ * @param locusId The locusId a unique, stable id that identifies this activity.
+ * @param appToken ActivityRecord's appToken.
+ * {@link UsageEvents}
+ * @hide
+ */
+ public abstract void reportLocusUpdate(@NonNull ComponentName activity, @UserIdInt int userId,
+ @Nullable LocusId locusId, @NonNull IBinder appToken);
+
/**
* Prepares the UsageStatsService for shutdown.
*/
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 994c3147d70c..27b6bfb8f5fd 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -252,11 +252,23 @@ public abstract class PackageManagerInternal {
String packageName, int userId);
/**
+ * Do a straight uid lookup for the given package/application in the given user. This enforces
+ * app visibility rules and permissions. Call {@link #getPackageUidInternal} for the internal
+ * implementation.
+ * @deprecated Use {@link PackageManager#getPackageUid(String, int)}
+ * @return The app's uid, or < 0 if the package was not found in that user
+ */
+ @Deprecated
+ public abstract int getPackageUid(String packageName,
+ @PackageInfoFlags int flags, int userId);
+
+ /**
* Do a straight uid lookup for the given package/application in the given user.
* @see PackageManager#getPackageUidAsUser(String, int, int)
* @return The app's uid, or < 0 if the package was not found in that user
+ * TODO(b/148235092): rename this to getPackageUid
*/
- public abstract int getPackageUid(String packageName,
+ public abstract int getPackageUidInternal(String packageName,
@PackageInfoFlags int flags, int userId);
/**
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 882b417dd679..dd33566322e2 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -64,6 +64,7 @@ import android.net.CaptivePortal;
import android.net.ConnectionInfo;
import android.net.ConnectivityManager;
import android.net.ICaptivePortal;
+import android.net.IConnectivityDiagnosticsCallback;
import android.net.IConnectivityManager;
import android.net.IDnsResolver;
import android.net.IIpConnectivityMetrics;
@@ -1623,7 +1624,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
}
- private NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
+ @VisibleForTesting
+ NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
NetworkCapabilities nc, int callerPid, int callerUid) {
final NetworkCapabilities newNc = new NetworkCapabilities(nc);
if (!checkSettingsPermission(callerPid, callerUid)) {
@@ -1634,9 +1636,23 @@ public class ConnectivityService extends IConnectivityManager.Stub
newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact());
}
newNc.setAdministratorUids(Collections.EMPTY_LIST);
+
+ maybeSanitizeLocationInfoForCaller(newNc, callerUid);
+
return newNc;
}
+ private void maybeSanitizeLocationInfoForCaller(
+ NetworkCapabilities nc, int callerUid) {
+ // TODO(b/142072839): Conditionally reset the owner UID if the following
+ // conditions are not met:
+ // 1. The destination app is the network owner
+ // 2. The destination app has the ACCESS_COARSE_LOCATION permission granted
+ // if target SDK<29 or otherwise has the ACCESS_FINE_LOCATION permission granted
+ // 3. The user's location toggle is on
+ nc.setOwnerUid(INVALID_UID);
+ }
+
private LinkProperties linkPropertiesRestrictedForCallerPermissions(
LinkProperties lp, int callerPid, int callerUid) {
if (lp == null) return new LinkProperties();
@@ -1665,6 +1681,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
nc.setSingleUid(Binder.getCallingUid());
}
nc.setAdministratorUids(Collections.EMPTY_LIST);
+
+ // Clear owner UID; this can never come from an app.
+ nc.setOwnerUid(INVALID_UID);
}
private void restrictBackgroundRequestForCaller(NetworkCapabilities nc) {
@@ -5801,7 +5820,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
final Set<UidRange> ranges = nai.networkCapabilities.getUids();
- final int vpnAppUid = nai.networkCapabilities.getEstablishingVpnAppUid();
+ final int vpnAppUid = nai.networkCapabilities.getOwnerUid();
// TODO: this create a window of opportunity for apps to receive traffic between the time
// when the old rules are removed and the time when new rules are added. To fix this,
// make eBPF support two whitelisted interfaces so here new rules can be added before the
@@ -6000,7 +6019,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (nc == null || lp == null) return false;
return nai.isVPN()
&& !nai.networkAgentConfig.allowBypass
- && nc.getEstablishingVpnAppUid() != Process.SYSTEM_UID
+ && nc.getOwnerUid() != Process.SYSTEM_UID
&& lp.getInterfaceName() != null
&& (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute());
}
@@ -6048,12 +6067,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
// TODO Fix this window by computing an accurate diff on Set<UidRange>, so the old range
// to be removed will never overlap with the new range to be added.
if (wasFiltering && !prevRanges.isEmpty()) {
- mPermissionMonitor.onVpnUidRangesRemoved(iface, prevRanges,
- prevNc.getEstablishingVpnAppUid());
+ mPermissionMonitor.onVpnUidRangesRemoved(iface, prevRanges, prevNc.getOwnerUid());
}
if (shouldFilter && !newRanges.isEmpty()) {
- mPermissionMonitor.onVpnUidRangesAdded(iface, newRanges,
- newNc.getEstablishingVpnAppUid());
+ mPermissionMonitor.onVpnUidRangesAdded(iface, newRanges, newNc.getOwnerUid());
}
} catch (Exception e) {
// Never crash!
@@ -7314,4 +7331,20 @@ public class ConnectivityService extends IConnectivityManager.Stub
return mTNS;
}
}
+
+ @Override
+ public void registerConnectivityDiagnosticsCallback(
+ @NonNull IConnectivityDiagnosticsCallback callback, @NonNull NetworkRequest request) {
+ // TODO(b/146444622): implement register IConnectivityDiagnosticsCallback functionality
+ throw new UnsupportedOperationException(
+ "registerConnectivityDiagnosticsCallback not yet implemented");
+ }
+
+ @Override
+ public void unregisterConnectivityDiagnosticsCallback(
+ @NonNull IConnectivityDiagnosticsCallback callback) {
+ // TODO(b/146444622): implement register IConnectivityDiagnosticsCallback functionality
+ throw new UnsupportedOperationException(
+ "unregisterConnectivityDiagnosticsCallback not yet implemented");
+ }
}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index de0b6fcbd4ae..3b6ff26d5f03 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -52,6 +52,7 @@ import android.location.ILocationListener;
import android.location.ILocationManager;
import android.location.Location;
import android.location.LocationManager;
+import android.location.LocationManagerInternal;
import android.location.LocationRequest;
import android.location.LocationTime;
import android.os.Binder;
@@ -133,11 +134,12 @@ public class LocationManagerService extends ILocationManager.Stub {
*/
public static class Lifecycle extends SystemService {
- private LocationManagerService mService;
+ private final LocationManagerService mService;
public Lifecycle(Context context) {
super(context);
mService = new LocationManagerService(context);
+ LocalServices.addService(LocationManagerInternal.class, mService.new LocalService());
}
@Override
@@ -465,7 +467,7 @@ public class LocationManagerService extends ILocationManager.Stub {
mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
for (LocationProviderManager manager : mProviderManagers) {
- manager.onUseableChangedLocked(userId);
+ manager.onEnabledChangedLocked(userId);
}
}
@@ -633,10 +635,10 @@ public class LocationManagerService extends ILocationManager.Stub {
for (LocationProviderManager manager : mProviderManagers) {
// update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility
mSettingsStore.setLocationProviderAllowed(manager.getName(),
- manager.isUseable(newUserId), newUserId);
+ manager.isEnabled(newUserId), newUserId);
- manager.onUseableChangedLocked(oldUserId);
- manager.onUseableChangedLocked(newUserId);
+ manager.onEnabledChangedLocked(oldUserId);
+ manager.onEnabledChangedLocked(newUserId);
}
}
@@ -650,22 +652,22 @@ public class LocationManagerService extends ILocationManager.Stub {
// acquiring mLock makes operations on mProvider atomic, but is otherwise unnecessary
protected final MockableLocationProvider mProvider;
- // useable state for parent user ids, no entry implies false. location state is only kept
+ // enabled state for parent user ids, no entry implies false. location state is only kept
// for parent user ids, the location state for a profile user id is assumed to be the same
// as for the parent. if querying this structure, ensure that the user id being used is a
// parent id or the results may be incorrect.
@GuardedBy("mLock")
- private final SparseArray<Boolean> mUseable;
+ private final SparseArray<Boolean> mEnabled;
private LocationProviderManager(String name) {
mName = name;
- mUseable = new SparseArray<>(1);
+ mEnabled = new SparseArray<>(1);
// initialize last since this lets our reference escape
mProvider = new MockableLocationProvider(mContext, mLock, this);
- // we can assume all users start with unuseable location state since the initial state
- // of all providers is disabled. no need to initialize mUseable further.
+ // we can assume all users start with disabled location state since the initial state
+ // of all providers is disabled. no need to initialize mEnabled further.
}
public String getName() {
@@ -693,13 +695,13 @@ public class LocationManagerService extends ILocationManager.Stub {
return mProvider.getState().properties;
}
- public void setMockProviderEnabled(boolean enabled) {
+ public void setMockProviderAllowed(boolean enabled) {
synchronized (mLock) {
if (!mProvider.isMock()) {
throw new IllegalArgumentException(mName + " provider is not a test provider");
}
- mProvider.setMockProviderEnabled(enabled);
+ mProvider.setMockProviderAllowed(enabled);
}
}
@@ -760,7 +762,7 @@ public class LocationManagerService extends ILocationManager.Stub {
return;
}
- if (!GPS_PROVIDER.equals(mName) || !isUseable()) {
+ if (!GPS_PROVIDER.equals(mName) || !isEnabled()) {
Slog.w(TAG, "reportLocationBatch() called without user permission");
return;
}
@@ -771,30 +773,33 @@ public class LocationManagerService extends ILocationManager.Stub {
@GuardedBy("mLock")
@Override
public void onStateChanged(State oldState, State newState) {
- if (oldState.enabled != newState.enabled) {
+ if (oldState.allowed != newState.allowed) {
// it would be more correct to call this for all users, but we know this can
// only affect the current user since providers are disabled for non-current
// users
- onUseableChangedLocked(mUserInfoStore.getCurrentUserId());
+ onEnabledChangedLocked(mUserInfoStore.getCurrentUserId());
}
}
- public boolean isUseable() {
- return isUseable(mUserInfoStore.getCurrentUserId());
+ public void requestSetAllowed(boolean allowed) {
+ mProvider.requestSetAllowed(allowed);
}
- public boolean isUseable(int userId) {
+ public boolean isEnabled() {
+ return isEnabled(mUserInfoStore.getCurrentUserId());
+ }
+
+ public boolean isEnabled(int userId) {
synchronized (mLock) {
// normalize user id to always refer to parent since profile state is always the
// same as parent state
userId = mUserInfoStore.getParentUserId(userId);
-
- return mUseable.get(userId, Boolean.FALSE);
+ return mEnabled.get(userId, Boolean.FALSE);
}
}
@GuardedBy("mLock")
- public void onUseableChangedLocked(int userId) {
+ public void onEnabledChangedLocked(int userId) {
if (userId == UserHandle.USER_NULL) {
// only used during initialization - we don't care about the null user
return;
@@ -804,36 +809,36 @@ public class LocationManagerService extends ILocationManager.Stub {
// as parent state
userId = mUserInfoStore.getParentUserId(userId);
- // if any property that contributes to "useability" here changes state, it MUST result
- // in a direct or indrect call to onUseableChangedLocked. this allows the provider to
+ // if any property that contributes to "enabled" here changes state, it MUST result
+ // in a direct or indrect call to onEnabledChangedLocked. this allows the provider to
// guarantee that it will always eventually reach the correct state.
- boolean useable = (userId == mUserInfoStore.getCurrentUserId())
- && mSettingsStore.isLocationEnabled(userId) && mProvider.getState().enabled;
+ boolean enabled = (userId == mUserInfoStore.getCurrentUserId())
+ && mSettingsStore.isLocationEnabled(userId) && mProvider.getState().allowed;
- if (useable == isUseable(userId)) {
+ if (enabled == isEnabled(userId)) {
return;
}
- mUseable.put(userId, useable);
+ mEnabled.put(userId, enabled);
if (D) {
- Log.d(TAG, "[u" + userId + "] " + mName + " provider useable = " + useable);
+ Log.d(TAG, "[u" + userId + "] " + mName + " provider enabled = " + enabled);
}
// fused and passive provider never get public updates for legacy reasons
if (!FUSED_PROVIDER.equals(mName) && !PASSIVE_PROVIDER.equals(mName)) {
// update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility
- mSettingsStore.setLocationProviderAllowed(mName, useable, userId);
+ mSettingsStore.setLocationProviderAllowed(mName, enabled, userId);
Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION)
.putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName)
- .putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, useable)
+ .putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, enabled)
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
}
- if (!useable) {
+ if (!enabled) {
// If any provider has been disabled, clear all last locations for all
// providers. This is to be on the safe side in case a provider has location
// derived from this disabled provider.
@@ -841,7 +846,7 @@ public class LocationManagerService extends ILocationManager.Stub {
mLastLocationCoarseInterval.clear();
}
- updateProviderUseableLocked(this);
+ updateProviderEnabledLocked(this);
}
public void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
@@ -854,10 +859,10 @@ public class LocationManagerService extends ILocationManager.Stub {
pw.increaseIndent();
- boolean useable = isUseable();
- pw.println("useable=" + useable);
- if (!useable) {
- pw.println("enabled=" + mProvider.getState().enabled);
+ boolean enabled = isEnabled();
+ pw.println("enabled=" + enabled);
+ if (!enabled) {
+ pw.println("allowed=" + mProvider.getState().allowed);
}
pw.println("properties=" + mProvider.getState().properties);
@@ -1009,7 +1014,7 @@ public class LocationManagerService extends ILocationManager.Stub {
if (manager == null) {
continue;
}
- if (!manager.isUseable() && !isSettingsExemptLocked(updateRecord)) {
+ if (!manager.isEnabled() && !isSettingsExemptLocked(updateRecord)) {
continue;
}
@@ -1425,7 +1430,7 @@ public class LocationManagerService extends ILocationManager.Stub {
if (FUSED_PROVIDER.equals(name)) {
continue;
}
- if (enabledOnly && !manager.isUseable()) {
+ if (enabledOnly && !manager.isEnabled()) {
continue;
}
if (criteria != null
@@ -1467,8 +1472,8 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@GuardedBy("mLock")
- private void updateProviderUseableLocked(LocationProviderManager manager) {
- boolean useable = manager.isUseable();
+ private void updateProviderEnabledLocked(LocationProviderManager manager) {
+ boolean enabled = manager.isEnabled();
ArrayList<Receiver> deadReceivers = null;
@@ -1486,7 +1491,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
// Sends a notification message to the receiver
- if (!record.mReceiver.callProviderEnabledLocked(manager.getName(), useable)) {
+ if (!record.mReceiver.callProviderEnabledLocked(manager.getName(), enabled)) {
if (deadReceivers == null) {
deadReceivers = new ArrayList<>();
}
@@ -1553,7 +1558,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
final boolean isBatterySaverDisablingLocation = shouldThrottleRequests
|| (isForegroundOnlyMode && !record.mIsForegroundUid);
- if (!manager.isUseable() || isBatterySaverDisablingLocation) {
+ if (!manager.isEnabled() || isBatterySaverDisablingLocation) {
if (isSettingsExemptLocked(record)) {
providerRequest.setLocationSettingsIgnored(true);
providerRequest.setLowPowerMode(false);
@@ -1970,7 +1975,7 @@ public class LocationManagerService extends ILocationManager.Stub {
oldRecord.disposeLocked(false);
}
- if (!manager.isUseable() && !isSettingsExemptLocked(record)) {
+ if (!manager.isEnabled() && !isSettingsExemptLocked(record)) {
// Notify the listener that updates are currently disabled - but only if the request
// does not ignore location settings
receiver.callProviderEnabledLocked(name, false);
@@ -2082,7 +2087,7 @@ public class LocationManagerService extends ILocationManager.Stub {
return null;
}
- if (!manager.isUseable()) {
+ if (!manager.isEnabled()) {
return null;
}
@@ -2204,7 +2209,7 @@ public class LocationManagerService extends ILocationManager.Stub {
synchronized (mLock) {
LocationProviderManager manager = getLocationProviderManager(location.getProvider());
- if (manager == null || !manager.isUseable()) {
+ if (manager == null || !manager.isEnabled()) {
return false;
}
@@ -2491,7 +2496,7 @@ public class LocationManagerService extends ILocationManager.Stub {
synchronized (mLock) {
LocationProviderManager manager = getLocationProviderManager(providerName);
- return manager != null && manager.isUseable(userId);
+ return manager != null && manager.isEnabled(userId);
}
}
@@ -2549,8 +2554,8 @@ public class LocationManagerService extends ILocationManager.Stub {
long now = SystemClock.elapsedRealtime();
- // only update last location for locations that come from useable providers
- if (manager.isUseable()) {
+ // only update last location for locations that come from enabled providers
+ if (manager.isEnabled()) {
updateLastLocationLocked(location, manager.getName());
}
@@ -2560,7 +2565,7 @@ public class LocationManagerService extends ILocationManager.Stub {
if (lastLocationCoarseInterval == null) {
lastLocationCoarseInterval = new Location(location);
- if (manager.isUseable()) {
+ if (manager.isEnabled()) {
mLastLocationCoarseInterval.put(manager.getName(), lastLocationCoarseInterval);
}
}
@@ -2593,7 +2598,7 @@ public class LocationManagerService extends ILocationManager.Stub {
Receiver receiver = r.mReceiver;
boolean receiverDead = false;
- if (!manager.isUseable() && !isSettingsExemptLocked(r)) {
+ if (!manager.isEnabled() && !isSettingsExemptLocked(r)) {
continue;
}
@@ -2812,7 +2817,7 @@ public class LocationManagerService extends ILocationManager.Stub {
throw new IllegalArgumentException("provider doesn't exist: " + provider);
}
- manager.setMockProviderEnabled(enabled);
+ manager.setMockProviderAllowed(enabled);
}
@Override
@@ -2946,4 +2951,19 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
}
+
+ private class LocalService extends LocationManagerInternal {
+
+ @Override
+ public void requestSetProviderAllowed(String provider, boolean allowed) {
+ Preconditions.checkArgument(provider != null, "invalid null provider");
+
+ synchronized (mLock) {
+ LocationProviderManager manager = getLocationProviderManager(provider);
+ if (manager != null) {
+ manager.requestSetAllowed(allowed);
+ }
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5596b2fcb762..41a4bd433be5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -199,6 +199,7 @@ import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.LocusId;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityPresentationInfo;
import android.content.pm.ApplicationInfo;
@@ -19642,4 +19643,19 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
}
+
+ @Override
+ public void setActivityLocusContext(ComponentName activity, LocusId locusId, IBinder appToken) {
+ final int callingUid = Binder.getCallingUid();
+ final int userId = UserHandle.getCallingUserId();
+ if (getPackageManagerInternalLocked().getPackageUid(activity.getPackageName(),
+ /*flags=*/ 0, userId) != callingUid) {
+ throw new SecurityException("Calling uid " + callingUid + " cannot set locusId"
+ + "for package " + activity.getPackageName());
+ }
+
+ if (mUsageStatsService != null) {
+ mUsageStatsService.reportLocusUpdate(activity, userId, locusId, appToken);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 0c9abae2e0fc..423e0212dfd6 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -954,7 +954,7 @@ public class Vpn {
NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig();
networkAgentConfig.allowBypass = mConfig.allowBypass && !mLockdown;
- mNetworkCapabilities.setEstablishingVpnAppUid(Binder.getCallingUid());
+ mNetworkCapabilities.setOwnerUid(Binder.getCallingUid());
mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserHandle,
mConfig.allowedApplications, mConfig.disallowedApplications));
long token = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index 442211f451ee..214dcc0220ff 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -17,16 +17,15 @@
package com.android.server.integrity;
import static android.content.Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION;
+import static android.content.Intent.EXTRA_LONG_VERSION_CODE;
import static android.content.Intent.EXTRA_ORIGINATING_UID;
import static android.content.Intent.EXTRA_PACKAGE_NAME;
-import static android.content.Intent.EXTRA_VERSION_CODE;
import static android.content.integrity.AppIntegrityManager.EXTRA_STATUS;
import static android.content.integrity.AppIntegrityManager.STATUS_FAILURE;
import static android.content.integrity.AppIntegrityManager.STATUS_SUCCESS;
+import static android.content.integrity.IntegrityUtils.getHexDigest;
import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID;
-import static com.android.server.integrity.IntegrityUtils.getHexDigest;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
@@ -75,18 +74,29 @@ import java.util.Map;
/** Implementation of {@link AppIntegrityManagerService}. */
public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
+ /**
+ * This string will be used as the "installer" for formula evaluation when the app's installer
+ * cannot be determined.
+ *
+ * <p>This may happen for various reasons. e.g., the installing app's package name may not match
+ * its UID.
+ */
+ private static final String UNKNOWN_INSTALLER = "";
+ /**
+ * This string will be used as the "installer" for formula evaluation when the app is being
+ * installed via ADB.
+ */
+ private static final String ADB_INSTALLER = "adb";
+
private static final String TAG = "AppIntegrityManagerServiceImpl";
private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
- private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
private static final String PACKAGE_INSTALLER = "com.google.android.packageinstaller";
private static final String BASE_APK_FILE = "base.apk";
private static final String ALLOWED_INSTALLERS_METADATA_NAME = "allowed-installers";
private static final String ALLOWED_INSTALLER_DELIMITER = ",";
private static final String INSTALLER_PACKAGE_CERT_DELIMITER = "\\|";
- private static final String ADB_INSTALLER = "adb";
- private static final String UNKNOWN_INSTALLER = "";
private static final String INSTALLER_CERT_NOT_APPLICABLE = "";
// Access to files inside mRulesDir is protected by mRulesLock;
@@ -241,7 +251,7 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
builder.setPackageName(getPackageNameNormalized(packageName));
builder.setAppCertificate(appCert == null ? "" : appCert);
- builder.setVersionCode(intent.getIntExtra(EXTRA_VERSION_CODE, -1));
+ builder.setVersionCode(intent.getLongExtra(EXTRA_LONG_VERSION_CODE, -1));
builder.setInstallerName(getPackageNameNormalized(installerPackageName));
builder.setInstallerCertificate(
getInstallerCertificateFingerprint(installerPackageName));
@@ -262,14 +272,11 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
+ " due to "
+ result.getRule());
- // TODO(b/147095027): Remove when the proto type is fixed.
- int dummyBreakageFixerInt = 0;
-
StatsLog.write(
StatsLog.INTEGRITY_CHECK_RESULT_REPORTED,
packageName,
appCert,
- dummyBreakageFixerInt,
+ appInstallMetadata.getVersionCode(),
installerPackageName,
getLoggingResponse(result),
isCausedByAppCertRule(result),
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java b/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
index 07eacbfd87dd..1a6b3d8b8411 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
+++ b/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
@@ -19,7 +19,7 @@ package com.android.server.integrity.engine;
import android.content.integrity.AppInstallMetadata;
import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
import android.content.integrity.Rule;
import android.util.Slog;
@@ -65,7 +65,7 @@ public class RuleEvaluationEngine {
* Load, and match the list of rules against an app install metadata.
*
* @param appInstallMetadata Metadata of the app to be installed, and to evaluate the rules
- * against.
+ * against.
* @return result of the integrity check
*/
public IntegrityCheckResult evaluate(
@@ -89,14 +89,14 @@ public class RuleEvaluationEngine {
return Optional.empty();
}
- List<Formula> formulas = new ArrayList<>(allowedInstallers.size());
+ List<IntegrityFormula> formulas = new ArrayList<>(allowedInstallers.size());
allowedInstallers.forEach(
(installer, cert) -> {
formulas.add(allowedInstallerFormula(installer, cert));
});
// We need this special case since OR-formulas require at least two operands.
- Formula allInstallersFormula =
+ IntegrityFormula allInstallersFormula =
formulas.size() == 1
? formulas.get(0)
: new CompoundFormula(CompoundFormula.OR, formulas);
@@ -108,7 +108,7 @@ public class RuleEvaluationEngine {
Rule.DENY));
}
- private static Formula allowedInstallerFormula(String installer, String cert) {
+ private static IntegrityFormula allowedInstallerFormula(String installer, String cert) {
return new CompoundFormula(
CompoundFormula.AND,
Arrays.asList(
@@ -117,8 +117,7 @@ public class RuleEvaluationEngine {
installer,
/* isHashedValue= */ false),
new AtomicFormula.StringAtomicFormula(
- AtomicFormula.INSTALLER_CERTIFICATE,
- cert,
- /* isHashedValue= */ false)));
+ AtomicFormula.INSTALLER_CERTIFICATE, cert, /* isHashedValue= */
+ false)));
}
}
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java b/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
index b1c20d27c792..66537ff6105e 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
+++ b/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
@@ -22,7 +22,6 @@ import static android.content.integrity.Rule.FORCE_ALLOW;
import android.annotation.NonNull;
import android.content.integrity.AppInstallMetadata;
import android.content.integrity.Rule;
-import android.util.Slog;
import com.android.server.integrity.model.IntegrityCheckResult;
@@ -35,8 +34,6 @@ import java.util.List;
*/
final class RuleEvaluator {
- private static final String TAG = "RuleEvaluator";
-
/**
* Match the list of rules against an app install metadata.
*
@@ -53,7 +50,7 @@ final class RuleEvaluator {
List<Rule> rules, AppInstallMetadata appInstallMetadata) {
List<Rule> matchedRules = new ArrayList<>();
for (Rule rule : rules) {
- if (rule.getFormula().isSatisfied(appInstallMetadata)) {
+ if (rule.getFormula().matches(appInstallMetadata)) {
matchedRules.add(rule);
}
}
@@ -71,8 +68,7 @@ final class RuleEvaluator {
case FORCE_ALLOW:
return IntegrityCheckResult.allow(rule);
default:
- Slog.e(TAG, "Matched an unknown effect rule: " + rule);
- return IntegrityCheckResult.allow();
+ throw new IllegalArgumentException("Matched an unknown effect rule: " + rule);
}
}
return denied ? IntegrityCheckResult.deny(denyRule) : IntegrityCheckResult.allow();
diff --git a/services/core/java/com/android/server/integrity/model/BitOutputStream.java b/services/core/java/com/android/server/integrity/model/BitOutputStream.java
index 7d1bb3fb8203..14b35fd016eb 100644
--- a/services/core/java/com/android/server/integrity/model/BitOutputStream.java
+++ b/services/core/java/com/android/server/integrity/model/BitOutputStream.java
@@ -61,7 +61,7 @@ public class BitOutputStream {
/**
* Set the next bit in the stream to value.
*
- * @param value The value to set the bit to.
+ * @param value The value to set the bit to
*/
public void setNext(boolean value) throws IOException {
int byteToWrite = mNextBitIndex / BYTE_BITS;
diff --git a/services/core/java/com/android/server/integrity/parser/BinaryFileOperations.java b/services/core/java/com/android/server/integrity/parser/BinaryFileOperations.java
index 2c5b7d3c122c..f09e035ecc78 100644
--- a/services/core/java/com/android/server/integrity/parser/BinaryFileOperations.java
+++ b/services/core/java/com/android/server/integrity/parser/BinaryFileOperations.java
@@ -19,7 +19,8 @@ package com.android.server.integrity.parser;
import static com.android.server.integrity.model.ComponentBitSize.IS_HASHED_BITS;
import static com.android.server.integrity.model.ComponentBitSize.VALUE_SIZE_BITS;
-import com.android.server.integrity.IntegrityUtils;
+import android.content.integrity.IntegrityUtils;
+
import com.android.server.integrity.model.BitInputStream;
import java.io.IOException;
diff --git a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
index 90954ff21d57..4b8efafcb6b0 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
@@ -35,7 +35,7 @@ import static com.android.server.integrity.parser.BinaryFileOperations.getString
import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
import android.content.integrity.Rule;
import com.android.server.integrity.model.BitInputStream;
@@ -121,7 +121,7 @@ public class RuleBinaryParser implements RuleParser {
}
private Rule parseRule(BitInputStream bitInputStream) throws IOException {
- Formula formula = parseFormula(bitInputStream);
+ IntegrityFormula formula = parseFormula(bitInputStream);
int effect = bitInputStream.getNext(EFFECT_BITS);
if (bitInputStream.getNext(SIGNAL_BIT) != 1) {
@@ -131,7 +131,7 @@ public class RuleBinaryParser implements RuleParser {
return new Rule(formula, effect);
}
- private Formula parseFormula(BitInputStream bitInputStream) throws IOException {
+ private IntegrityFormula parseFormula(BitInputStream bitInputStream) throws IOException {
int separator = bitInputStream.getNext(SEPARATOR_BITS);
switch (separator) {
case ATOMIC_FORMULA_START:
@@ -148,9 +148,9 @@ public class RuleBinaryParser implements RuleParser {
private CompoundFormula parseCompoundFormula(BitInputStream bitInputStream) throws IOException {
int connector = bitInputStream.getNext(CONNECTOR_BITS);
- List<Formula> formulas = new ArrayList<>();
+ List<IntegrityFormula> formulas = new ArrayList<>();
- Formula parsedFormula = parseFormula(bitInputStream);
+ IntegrityFormula parsedFormula = parseFormula(bitInputStream);
while (parsedFormula != null) {
formulas.add(parsedFormula);
parsedFormula = parseFormula(bitInputStream);
@@ -173,8 +173,11 @@ public class RuleBinaryParser implements RuleParser {
String stringValue = getStringValue(bitInputStream, valueSize, isHashedValue);
return new AtomicFormula.StringAtomicFormula(key, stringValue, isHashedValue);
case AtomicFormula.VERSION_CODE:
- int intValue = getIntValue(bitInputStream);
- return new AtomicFormula.IntAtomicFormula(key, operator, intValue);
+ // TODO(b/147880712): temporary hack until our input handles long
+ long upper = getIntValue(bitInputStream);
+ long lower = getIntValue(bitInputStream);
+ long longValue = (upper << 32) | lower;
+ return new AtomicFormula.LongAtomicFormula(key, operator, longValue);
case AtomicFormula.PRE_INSTALLED:
boolean booleanValue = getBooleanValue(bitInputStream);
return new AtomicFormula.BooleanAtomicFormula(key, booleanValue);
diff --git a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
index 53b0c2e59453..f37ca1efce13 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
@@ -18,7 +18,7 @@ package com.android.server.integrity.parser;
import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
import android.content.integrity.Rule;
import android.util.Xml;
@@ -107,7 +107,7 @@ public final class RuleXmlParser implements RuleParser {
}
private static Rule parseRule(XmlPullParser parser) throws IOException, XmlPullParserException {
- Formula formula = null;
+ IntegrityFormula formula = null;
int effect = Integer.parseInt(extractAttributeValue(parser, EFFECT_ATTRIBUTE).orElse("-1"));
int eventType;
@@ -139,11 +139,11 @@ public final class RuleXmlParser implements RuleParser {
return new Rule(formula, effect);
}
- private static Formula parseCompoundFormula(XmlPullParser parser)
+ private static IntegrityFormula parseCompoundFormula(XmlPullParser parser)
throws IOException, XmlPullParserException {
int connector =
Integer.parseInt(extractAttributeValue(parser, CONNECTOR_ATTRIBUTE).orElse("-1"));
- List<Formula> formulas = new ArrayList<>();
+ List<IntegrityFormula> formulas = new ArrayList<>();
int eventType;
while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) {
@@ -175,7 +175,7 @@ public final class RuleXmlParser implements RuleParser {
return new CompoundFormula(connector, formulas);
}
- private static Formula parseAtomicFormula(XmlPullParser parser)
+ private static IntegrityFormula parseAtomicFormula(XmlPullParser parser)
throws IOException, XmlPullParserException {
int key = Integer.parseInt(extractAttributeValue(parser, KEY_ATTRIBUTE).orElse("-1"));
int operator =
@@ -193,7 +193,7 @@ public final class RuleXmlParser implements RuleParser {
return constructAtomicFormulaBasedOnKey(key, operator, value, isHashedValue);
}
- private static Formula constructAtomicFormulaBasedOnKey(
+ private static IntegrityFormula constructAtomicFormulaBasedOnKey(
@AtomicFormula.Key int key,
@AtomicFormula.Operator int operator,
String value,
@@ -208,7 +208,7 @@ public final class RuleXmlParser implements RuleParser {
case AtomicFormula.PRE_INSTALLED:
return new AtomicFormula.BooleanAtomicFormula(key, Boolean.parseBoolean(value));
case AtomicFormula.VERSION_CODE:
- return new AtomicFormula.IntAtomicFormula(key, operator, Integer.parseInt(value));
+ return new AtomicFormula.LongAtomicFormula(key, operator, Integer.parseInt(value));
default:
throw new RuntimeException(String.format("Found unexpected key: %d", key));
}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
index f5ed975bf772..d01499668e8c 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
@@ -36,11 +36,11 @@ import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAG
import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
+import android.content.integrity.IntegrityUtils;
import android.content.integrity.Rule;
import com.android.internal.util.Preconditions;
-import com.android.server.integrity.IntegrityUtils;
import com.android.server.integrity.model.BitOutputStream;
import com.android.server.integrity.model.ByteTrackedOutputStream;
@@ -192,7 +192,7 @@ public class RuleBinarySerializer implements RuleSerializer {
bitOutputStream.setNext();
}
- private void serializeFormula(Formula formula, BitOutputStream bitOutputStream)
+ private void serializeFormula(IntegrityFormula formula, BitOutputStream bitOutputStream)
throws IOException {
if (formula instanceof AtomicFormula) {
serializeAtomicFormula((AtomicFormula) formula, bitOutputStream);
@@ -212,7 +212,7 @@ public class RuleBinarySerializer implements RuleSerializer {
bitOutputStream.setNext(SEPARATOR_BITS, COMPOUND_FORMULA_START);
bitOutputStream.setNext(CONNECTOR_BITS, compoundFormula.getConnector());
- for (Formula formula : compoundFormula.getFormulas()) {
+ for (IntegrityFormula formula : compoundFormula.getFormulas()) {
serializeFormula(formula, bitOutputStream);
}
bitOutputStream.setNext(SEPARATOR_BITS, COMPOUND_FORMULA_END);
@@ -234,11 +234,14 @@ public class RuleBinarySerializer implements RuleSerializer {
stringAtomicFormula.getValue(),
stringAtomicFormula.getIsHashedValue(),
bitOutputStream);
- } else if (atomicFormula.getTag() == AtomicFormula.INT_ATOMIC_FORMULA_TAG) {
- AtomicFormula.IntAtomicFormula intAtomicFormula =
- (AtomicFormula.IntAtomicFormula) atomicFormula;
- bitOutputStream.setNext(OPERATOR_BITS, intAtomicFormula.getOperator());
- serializeIntValue(intAtomicFormula.getValue(), bitOutputStream);
+ } else if (atomicFormula.getTag() == AtomicFormula.LONG_ATOMIC_FORMULA_TAG) {
+ AtomicFormula.LongAtomicFormula longAtomicFormula =
+ (AtomicFormula.LongAtomicFormula) atomicFormula;
+ bitOutputStream.setNext(OPERATOR_BITS, longAtomicFormula.getOperator());
+ // TODO(b/147880712): Temporary hack until we support long values in bitOutputStream
+ long value = longAtomicFormula.getValue();
+ serializeIntValue((int) (value >>> 32), bitOutputStream);
+ serializeIntValue((int) value, bitOutputStream);
} else if (atomicFormula.getTag() == AtomicFormula.BOOLEAN_ATOMIC_FORMULA_TAG) {
AtomicFormula.BooleanAtomicFormula booleanAtomicFormula =
(AtomicFormula.BooleanAtomicFormula) atomicFormula;
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java
index 7d9a90188983..6f7d172aabcc 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifier.java
@@ -22,7 +22,7 @@ import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAG
import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
import android.content.integrity.Rule;
import java.util.ArrayList;
@@ -76,15 +76,15 @@ class RuleIndexingDetailsIdentifier {
return typeOrganizedRuleMap;
}
- private static RuleIndexingDetails getIndexingDetails(Formula formula) {
+ private static RuleIndexingDetails getIndexingDetails(IntegrityFormula formula) {
switch (formula.getTag()) {
- case Formula.COMPOUND_FORMULA_TAG:
+ case IntegrityFormula.COMPOUND_FORMULA_TAG:
return getIndexingDetailsForCompoundFormula((CompoundFormula) formula);
- case Formula.STRING_ATOMIC_FORMULA_TAG:
+ case IntegrityFormula.STRING_ATOMIC_FORMULA_TAG:
return getIndexingDetailsForStringAtomicFormula(
(AtomicFormula.StringAtomicFormula) formula);
- case Formula.INT_ATOMIC_FORMULA_TAG:
- case Formula.BOOLEAN_ATOMIC_FORMULA_TAG:
+ case IntegrityFormula.LONG_ATOMIC_FORMULA_TAG:
+ case IntegrityFormula.BOOLEAN_ATOMIC_FORMULA_TAG:
// Package name and app certificate related formulas are string atomic formulas.
return new RuleIndexingDetails(NOT_INDEXED);
default:
@@ -96,7 +96,7 @@ class RuleIndexingDetailsIdentifier {
private static RuleIndexingDetails getIndexingDetailsForCompoundFormula(
CompoundFormula compoundFormula) {
int connector = compoundFormula.getConnector();
- List<Formula> formulas = compoundFormula.getFormulas();
+ List<IntegrityFormula> formulas = compoundFormula.getFormulas();
switch (connector) {
case CompoundFormula.AND:
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
index 8f164e645434..6e1218064096 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
@@ -22,7 +22,7 @@ import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAG
import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
import android.content.integrity.Rule;
import android.util.Xml;
@@ -128,7 +128,8 @@ public class RuleXmlSerializer implements RuleSerializer {
xmlSerializer.endTag(NAMESPACE, RULE_TAG);
}
- private void serializeFormula(Formula formula, XmlSerializer xmlSerializer) throws IOException {
+ private void serializeFormula(IntegrityFormula formula, XmlSerializer xmlSerializer)
+ throws IOException {
if (formula instanceof AtomicFormula) {
serializeAtomicFormula((AtomicFormula) formula, xmlSerializer);
} else if (formula instanceof CompoundFormula) {
@@ -147,7 +148,7 @@ public class RuleXmlSerializer implements RuleSerializer {
xmlSerializer.startTag(NAMESPACE, COMPOUND_FORMULA_TAG);
serializeAttributeValue(
CONNECTOR_ATTRIBUTE, String.valueOf(compoundFormula.getConnector()), xmlSerializer);
- for (Formula formula : compoundFormula.getFormulas()) {
+ for (IntegrityFormula formula : compoundFormula.getFormulas()) {
serializeFormula(formula, xmlSerializer);
}
xmlSerializer.endTag(NAMESPACE, COMPOUND_FORMULA_TAG);
@@ -171,14 +172,14 @@ public class RuleXmlSerializer implements RuleSerializer {
String.valueOf(
((AtomicFormula.StringAtomicFormula) atomicFormula).getIsHashedValue()),
xmlSerializer);
- } else if (atomicFormula.getTag() == AtomicFormula.INT_ATOMIC_FORMULA_TAG) {
+ } else if (atomicFormula.getTag() == AtomicFormula.LONG_ATOMIC_FORMULA_TAG) {
serializeAttributeValue(
OPERATOR_ATTRIBUTE,
- String.valueOf(((AtomicFormula.IntAtomicFormula) atomicFormula).getOperator()),
+ String.valueOf(((AtomicFormula.LongAtomicFormula) atomicFormula).getOperator()),
xmlSerializer);
serializeAttributeValue(
VALUE_ATTRIBUTE,
- String.valueOf(((AtomicFormula.IntAtomicFormula) atomicFormula).getValue()),
+ String.valueOf(((AtomicFormula.LongAtomicFormula) atomicFormula).getValue()),
xmlSerializer);
} else if (atomicFormula.getTag() == AtomicFormula.BOOLEAN_ATOMIC_FORMULA_TAG) {
serializeAttributeValue(
diff --git a/services/core/java/com/android/server/location/AbstractLocationProvider.java b/services/core/java/com/android/server/location/AbstractLocationProvider.java
index ed6a759409d4..5afa48a2b34d 100644
--- a/services/core/java/com/android/server/location/AbstractLocationProvider.java
+++ b/services/core/java/com/android/server/location/AbstractLocationProvider.java
@@ -79,9 +79,9 @@ public abstract class AbstractLocationProvider {
Collections.emptySet());
/**
- * The provider's enabled state.
+ * The provider's allowed state.
*/
- public final boolean enabled;
+ public final boolean allowed;
/**
* The provider's properties.
@@ -93,18 +93,18 @@ public abstract class AbstractLocationProvider {
*/
public final Set<String> providerPackageNames;
- private State(boolean enabled, ProviderProperties properties,
+ private State(boolean allowed, ProviderProperties properties,
Set<String> providerPackageNames) {
- this.enabled = enabled;
+ this.allowed = allowed;
this.properties = properties;
this.providerPackageNames = Objects.requireNonNull(providerPackageNames);
}
- private State withEnabled(boolean enabled) {
- if (enabled == this.enabled) {
+ private State withAllowed(boolean allowed) {
+ if (allowed == this.allowed) {
return this;
} else {
- return new State(enabled, properties, providerPackageNames);
+ return new State(allowed, properties, providerPackageNames);
}
}
@@ -112,7 +112,7 @@ public abstract class AbstractLocationProvider {
if (properties.equals(this.properties)) {
return this;
} else {
- return new State(enabled, properties, providerPackageNames);
+ return new State(allowed, properties, providerPackageNames);
}
}
@@ -120,7 +120,7 @@ public abstract class AbstractLocationProvider {
if (providerPackageNames.equals(this.providerPackageNames)) {
return this;
} else {
- return new State(enabled, properties, providerPackageNames);
+ return new State(allowed, properties, providerPackageNames);
}
}
@@ -133,13 +133,13 @@ public abstract class AbstractLocationProvider {
return false;
}
State state = (State) o;
- return enabled == state.enabled && properties == state.properties
+ return allowed == state.allowed && properties == state.properties
&& providerPackageNames.equals(state.providerPackageNames);
}
@Override
public int hashCode() {
- return Objects.hash(enabled, properties, providerPackageNames);
+ return Objects.hash(allowed, properties, providerPackageNames);
}
}
@@ -259,10 +259,10 @@ public abstract class AbstractLocationProvider {
}
/**
- * The current enabled state of this provider.
+ * The current allowed state of this provider.
*/
- protected boolean isEnabled() {
- return mInternalState.get().state.enabled;
+ protected boolean isAllowed() {
+ return mInternalState.get().state.allowed;
}
/**
@@ -281,10 +281,10 @@ public abstract class AbstractLocationProvider {
}
/**
- * Call this method to report a change in provider enabled/disabled status.
+ * Call this method to report a change in provider allowed status.
*/
- protected void setEnabled(boolean enabled) {
- setState(state -> state.withEnabled(enabled));
+ protected void setAllowed(boolean allowed) {
+ setState(state -> state.withAllowed(allowed));
}
/**
@@ -358,6 +358,19 @@ public abstract class AbstractLocationProvider {
protected void onExtraCommand(int uid, int pid, String command, Bundle extras) {}
/**
+ * Requests a provider to enable itself for the given user id.
+ */
+ public final void requestSetAllowed(boolean allowed) {
+ // all calls into the provider must be moved onto the provider thread to prevent deadlock
+ mExecutor.execute(() -> onRequestSetAllowed(allowed));
+ }
+
+ /**
+ * Always invoked on the provider executor.
+ */
+ protected void onRequestSetAllowed(boolean allowed) {}
+
+ /**
* Dumps debug or log information. May be invoked from any thread.
*/
public abstract void dump(FileDescriptor fd, PrintWriter pw, String[] args);
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 15cf190952d1..306e1e3afcd7 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -729,7 +729,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}, UserHandle.USER_ALL);
setProperties(PROPERTIES);
- setEnabled(true);
+ setAllowed(true);
}
/**
diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java
index 805b018a8f45..cf299fe9bb2a 100644
--- a/services/core/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/core/java/com/android/server/location/LocationProviderProxy.java
@@ -97,8 +97,8 @@ public class LocationProviderProxy extends AbstractLocationProvider {
// executed on binder thread
@Override
- public void onSetEnabled(boolean enabled) {
- setEnabled(enabled);
+ public void onSetAllowed(boolean allowed) {
+ setAllowed(allowed);
}
// executed on binder thread
@@ -169,6 +169,14 @@ public class LocationProviderProxy extends AbstractLocationProvider {
}
@Override
+ public void onRequestSetAllowed(boolean allowed) {
+ mServiceWatcher.runOnBinder(binder -> {
+ ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
+ service.requestSetAllowed(allowed);
+ });
+ }
+
+ @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("service=" + mServiceWatcher);
}
diff --git a/services/core/java/com/android/server/location/MockProvider.java b/services/core/java/com/android/server/location/MockProvider.java
index 60c9fc12c201..bcec8b12b371 100644
--- a/services/core/java/com/android/server/location/MockProvider.java
+++ b/services/core/java/com/android/server/location/MockProvider.java
@@ -42,9 +42,9 @@ public class MockProvider extends AbstractLocationProvider {
setProperties(properties);
}
- /** Sets the enabled state of this mock provider. */
- public void setProviderEnabled(boolean enabled) {
- setEnabled(enabled);
+ /** Sets the allowed state of this mock provider. */
+ public void setProviderAllowed(boolean allowed) {
+ setAllowed(allowed);
}
/** Sets the location to report for this mock provider. */
@@ -56,10 +56,15 @@ public class MockProvider extends AbstractLocationProvider {
}
@Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("last mock location=" + mLocation);
+ public void onSetRequest(ProviderRequest request) {}
+
+ @Override
+ protected void onRequestSetAllowed(boolean allowed) {
+ setAllowed(allowed);
}
@Override
- public void onSetRequest(ProviderRequest request) {}
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("last mock location=" + mLocation);
+ }
}
diff --git a/services/core/java/com/android/server/location/MockableLocationProvider.java b/services/core/java/com/android/server/location/MockableLocationProvider.java
index f50dfe7edbb7..18615f87609f 100644
--- a/services/core/java/com/android/server/location/MockableLocationProvider.java
+++ b/services/core/java/com/android/server/location/MockableLocationProvider.java
@@ -170,13 +170,13 @@ public class MockableLocationProvider extends AbstractLocationProvider {
}
/**
- * Sets the mock provider implementation's enabled state. Will throw an exception if the mock
+ * Sets the mock provider implementation's allowed state. Will throw an exception if the mock
* provider is not currently the active implementation.
*/
- public void setMockProviderEnabled(boolean enabled) {
+ public void setMockProviderAllowed(boolean allowed) {
synchronized (mOwnerLock) {
Preconditions.checkState(isMock());
- mMockProvider.setProviderEnabled(enabled);
+ mMockProvider.setProviderAllowed(allowed);
}
}
/**
diff --git a/services/core/java/com/android/server/location/PassiveProvider.java b/services/core/java/com/android/server/location/PassiveProvider.java
index b33877069d70..ef157a39fa28 100644
--- a/services/core/java/com/android/server/location/PassiveProvider.java
+++ b/services/core/java/com/android/server/location/PassiveProvider.java
@@ -56,7 +56,7 @@ public class PassiveProvider extends AbstractLocationProvider {
mReportLocation = false;
setProperties(PROPERTIES);
- setEnabled(true);
+ setAllowed(true);
}
@Override
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 7cc67324032a..e92f3ec5a836 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -513,6 +513,7 @@ public class NotificationManagerService extends SystemService {
private TriPredicate<String, Integer, String> mAllowedManagedServicePackages;
private final SavePolicyFileRunnable mSavePolicyFile = new SavePolicyFileRunnable();
+ private NotificationRecordLogger mNotificationRecordLogger;
private static class Archive {
final int mBufferSize;
@@ -1727,7 +1728,14 @@ public class NotificationManagerService extends SystemService {
}
public NotificationManagerService(Context context) {
+ this(context, new NotificationRecordLoggerImpl());
+ }
+
+ @VisibleForTesting
+ public NotificationManagerService(Context context,
+ NotificationRecordLogger notificationRecordLogger) {
super(context);
+ mNotificationRecordLogger = notificationRecordLogger;
Notification.processWhitelistToken = WHITELIST_TOKEN;
}
@@ -6304,9 +6312,11 @@ public class NotificationManagerService extends SystemService {
mRankingHelper.extractSignals(r);
mRankingHelper.sort(mNotificationList);
+ final int position = mRankingHelper.indexOf(mNotificationList, r);
+ int buzzBeepBlinkLoggingCode = 0;
if (!r.isHidden()) {
- buzzBeepBlinkLocked(r);
+ buzzBeepBlinkLoggingCode = buzzBeepBlinkLocked(r);
}
if (notification.getSmallIcon() != null) {
@@ -6346,6 +6356,10 @@ public class NotificationManagerService extends SystemService {
}
maybeRecordInterruptionLocked(r);
+
+ // Log event to statsd
+ mNotificationRecordLogger.logNotificationReported(r, old, position,
+ buzzBeepBlinkLoggingCode);
} finally {
int N = mEnqueuedNotifications.size();
for (int i = 0; i < N; i++) {
@@ -6574,9 +6588,13 @@ public class NotificationManagerService extends SystemService {
@VisibleForTesting
@GuardedBy("mNotificationLock")
- void buzzBeepBlinkLocked(NotificationRecord record) {
+ /**
+ * Determine whether this notification should attempt to make noise, vibrate, or flash the LED
+ * @return buzzBeepBlink - bitfield (buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0)
+ */
+ int buzzBeepBlinkLocked(NotificationRecord record) {
if (mIsAutomotive && !mNotificationEffectsEnabledForAutomotive) {
- return;
+ return 0;
}
boolean buzz = false;
boolean beep = false;
@@ -6674,7 +6692,8 @@ public class NotificationManagerService extends SystemService {
} else if (wasShowLights) {
updateLightsLocked();
}
- if (buzz || beep || blink) {
+ final int buzzBeepBlink = (buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0);
+ if (buzzBeepBlink > 0) {
// Ignore summary updates because we don't display most of the information.
if (record.sbn.isGroup() && record.sbn.getNotification().isGroupSummary()) {
if (DEBUG_INTERRUPTIVENESS) {
@@ -6696,10 +6715,11 @@ public class NotificationManagerService extends SystemService {
MetricsLogger.action(record.getLogMaker()
.setCategory(MetricsEvent.NOTIFICATION_ALERT)
.setType(MetricsEvent.TYPE_OPEN)
- .setSubtype((buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0)));
+ .setSubtype(buzzBeepBlink));
EventLogTags.writeNotificationAlert(key, buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0);
}
record.setAudiblyAlerted(buzz || beep);
+ return buzzBeepBlink;
}
@GuardedBy("mNotificationLock")
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 2bea21891f8f..660d574fe64e 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -675,6 +675,10 @@ public final class NotificationRecord {
}
}
+ String getAdjustmentIssuer() {
+ return mAdjustmentIssuer;
+ }
+
public void setIsAppImportanceLocked(boolean isAppImportanceLocked) {
mIsAppImportanceLocked = isAppImportanceLocked;
calculateUserSentiment();
@@ -783,10 +787,22 @@ public final class NotificationRecord {
return mImportance;
}
+ int getInitialImportance() {
+ return stats.naturalImportance;
+ }
+
public float getRankingScore() {
return mRankingScore;
}
+ int getImportanceExplanationCode() {
+ return mImportanceExplanationCode;
+ }
+
+ int getInitialImportanceExplanationCode() {
+ return mInitialImportanceExplanationCode;
+ }
+
public CharSequence getImportanceExplanation() {
switch (mImportanceExplanationCode) {
case MetricsEvent.IMPORTANCE_EXPLANATION_UNKNOWN:
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLogger.java b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
new file mode 100644
index 000000000000..03929e883852
--- /dev/null
+++ b/services/core/java/com/android/server/notification/NotificationRecordLogger.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2020 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.notification;
+
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.Person;
+import android.os.Bundle;
+
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
+
+import java.util.ArrayList;
+import java.util.Objects;
+
+/**
+ * Interface for writing NotificationReported atoms to statsd log.
+ * @hide
+ */
+public interface NotificationRecordLogger {
+
+ /**
+ * Logs a NotificationReported atom reflecting the posting or update of a notification.
+ * @param r The new NotificationRecord. If null, no action is taken.
+ * @param old The previous NotificationRecord. Null if there was no previous record.
+ * @param position The position at which this notification is ranked.
+ * @param buzzBeepBlink Logging code reflecting whether this notification alerted the user.
+ */
+ void logNotificationReported(@Nullable NotificationRecord r, @Nullable NotificationRecord old,
+ int position, int buzzBeepBlink);
+
+ /**
+ * The UiEvent enums that this class can log.
+ */
+ enum NotificationReportedEvents implements UiEventLogger.UiEventEnum {
+ INVALID(0),
+ @UiEvent(doc = "New notification enqueued to post")
+ NOTIFICATION_POSTED(162),
+ @UiEvent(doc = "Notification substantially updated")
+ NOTIFICATION_UPDATED(163);
+
+ private final int mId;
+ NotificationReportedEvents(int id) {
+ mId = id;
+ }
+ @Override public int getId() {
+ return mId;
+ }
+ }
+
+ /**
+ * A helper for extracting logging information from one or two NotificationRecords.
+ */
+ class NotificationRecordPair {
+ public final NotificationRecord r, old;
+ /**
+ * Construct from one or two NotificationRecords.
+ * @param r The new NotificationRecord. If null, only shouldLog() method is usable.
+ * @param old The previous NotificationRecord. Null if there was no previous record.
+ */
+ NotificationRecordPair(@Nullable NotificationRecord r, @Nullable NotificationRecord old) {
+ this.r = r;
+ this.old = old;
+ }
+
+ /**
+ * @return True if old is null, alerted, or important logged fields have changed.
+ */
+ boolean shouldLog(int buzzBeepBlink) {
+ if (r == null) {
+ return false;
+ }
+ if ((old == null) || (buzzBeepBlink > 0)) {
+ return true;
+ }
+
+ return !(Objects.equals(r.sbn.getChannelIdLogTag(), old.sbn.getChannelIdLogTag())
+ && Objects.equals(r.sbn.getGroupLogTag(), old.sbn.getGroupLogTag())
+ && (r.sbn.getNotification().isGroupSummary()
+ == old.sbn.getNotification().isGroupSummary())
+ && Objects.equals(r.sbn.getNotification().category,
+ old.sbn.getNotification().category)
+ && (r.getImportance() == old.getImportance()));
+ }
+
+ NotificationReportedEvents getUiEvent() {
+ return (old != null) ? NotificationReportedEvents.NOTIFICATION_UPDATED :
+ NotificationReportedEvents.NOTIFICATION_POSTED;
+ }
+
+ /**
+ * @return hash code for the notification style class, or 0 if none exists.
+ */
+ public int getStyle() {
+ return getStyle(r.sbn.getNotification().extras);
+ }
+
+ private int getStyle(@Nullable Bundle extras) {
+ if (extras != null) {
+ String template = extras.getString(Notification.EXTRA_TEMPLATE);
+ if (template != null && !template.isEmpty()) {
+ return template.hashCode();
+ }
+ }
+ return 0;
+ }
+
+ int getNumPeople() {
+ return getNumPeople(r.sbn.getNotification().extras);
+ }
+
+ private int getNumPeople(@Nullable Bundle extras) {
+ if (extras != null) {
+ ArrayList<Person> people = extras.getParcelableArrayList(
+ Notification.EXTRA_PEOPLE_LIST);
+ if (people != null && !people.isEmpty()) {
+ return people.size();
+ }
+ }
+ return 0;
+ }
+
+ int getAssistantHash() {
+ String assistant = r.getAdjustmentIssuer();
+ return (assistant == null) ? 0 : assistant.hashCode();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
new file mode 100644
index 000000000000..d637ad5e368b
--- /dev/null
+++ b/services/core/java/com/android/server/notification/NotificationRecordLoggerImpl.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2020 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.notification;
+
+import android.util.StatsLog;
+
+/**
+ * Standard implementation of NotificationRecordLogger interface.
+ * @hide
+ */
+public class NotificationRecordLoggerImpl implements NotificationRecordLogger {
+
+ @Override
+ public void logNotificationReported(NotificationRecord r, NotificationRecord old,
+ int position, int buzzBeepBlink) {
+ NotificationRecordPair p = new NotificationRecordPair(r, old);
+ if (!p.shouldLog(buzzBeepBlink)) {
+ return;
+ }
+ StatsLog.write(StatsLog.NOTIFICATION_REPORTED,
+ /* int32 event_id = 1 */ p.getUiEvent().getId(),
+ /* int32 uid = 2 */ r.getUid(),
+ /* string package_name = 3 */ r.sbn.getPackageName(),
+ /* int32 instance_id = 4 */ 0, // TODO generate and fill instance ids
+ /* int32 notification_id = 5 */ r.sbn.getId(),
+ /* string notification_tag = 6 */ r.sbn.getTag(),
+ /* string channel_id = 7 */ r.sbn.getChannelIdLogTag(),
+ /* string group_id = 8 */ r.sbn.getGroupLogTag(),
+ /* int32 group_instance_id = 9 */ 0, // TODO generate and fill instance ids
+ /* bool is_group_summary = 10 */ r.sbn.getNotification().isGroupSummary(),
+ /* string category = 11 */ r.sbn.getNotification().category,
+ /* int32 style = 12 */ p.getStyle(),
+ /* int32 num_people = 13 */ p.getNumPeople(),
+ /* int32 position = 14 */ position,
+ /* android.stats.sysui.NotificationImportance importance = 15 */ r.getImportance(),
+ /* int32 alerting = 16 */ buzzBeepBlink,
+ /* NotificationImportanceExplanation importance_source = 17 */
+ r.getImportanceExplanationCode(),
+ /* android.stats.sysui.NotificationImportance importance_initial = 18 */
+ r.getInitialImportance(),
+ /* NotificationImportanceExplanation importance_initial_source = 19 */
+ r.getInitialImportanceExplanationCode(),
+ /* android.stats.sysui.NotificationImportance importance_asst = 20 */
+ r.getAssistantImportance(),
+ /* int32 assistant_hash = 21 */ p.getAssistantHash(),
+ /* float assistant_ranking_score = 22 */ 0 // TODO connect up ranking score
+ );
+ }
+
+
+
+
+
+
+}
diff --git a/services/core/java/com/android/server/om/OverlayActorEnforcer.java b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
index ac3bf9ad5d8a..0a9f923ac817 100644
--- a/services/core/java/com/android/server/om/OverlayActorEnforcer.java
+++ b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
@@ -43,6 +43,9 @@ import java.util.Map;
*/
public class OverlayActorEnforcer {
+ // By default, the reason is not logged to prevent leaks of why it failed
+ private static final boolean DEBUG_REASON = false;
+
private final VerifyCallback mVerifyCallback;
/**
@@ -92,7 +95,7 @@ public class OverlayActorEnforcer {
throw new SecurityException("UID" + callingUid + " is not allowed to call "
+ methodName + " for "
+ (TextUtils.isEmpty(targetOverlayableName) ? "" : (targetOverlayableName + " in "))
- + overlayInfo.targetPackageName + " because " + actorState
+ + overlayInfo.targetPackageName + (DEBUG_REASON ? (" because " + actorState) : "")
);
}
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 9dff7754c4f3..6e7e5d884a4a 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -662,7 +662,7 @@ public class AppsFilter {
String description, Throwable throwable) {
Slog.wtf(TAG,
"interaction: " + callingPkgSetting
- + " -> " + targetPkgSetting.name + " "
+ + " -> " + targetPkgSetting + " "
+ description, throwable);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ca4ae0277aaf..d54b104731dc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -27,6 +27,7 @@ import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.content.Intent.ACTION_MAIN;
import static android.content.Intent.CATEGORY_DEFAULT;
import static android.content.Intent.CATEGORY_HOME;
+import static android.content.Intent.EXTRA_LONG_VERSION_CODE;
import static android.content.Intent.EXTRA_PACKAGE_NAME;
import static android.content.Intent.EXTRA_VERSION_CODE;
import static android.content.pm.PackageManager.CERT_INPUT_RAW_X509;
@@ -124,8 +125,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
-import android.app.ApplicationPackageManager;
import android.app.AppOpsManager;
+import android.app.ApplicationPackageManager;
import android.app.BroadcastOptions;
import android.app.IActivityManager;
import android.app.ResourcesManager;
@@ -4554,7 +4555,10 @@ public class PackageManagerService extends IPackageManager.Stub
flags = updateFlagsForPackage(flags, userId);
mPermissionManager.enforceCrossUserPermission(callingUid, userId,
false /*requireFullPermission*/, false /*checkShell*/, "getPackageUid");
+ return getPackageUidInternal(packageName, flags, userId, callingUid);
+ }
+ private int getPackageUidInternal(String packageName, int flags, int userId, int callingUid) {
// reader
synchronized (mLock) {
final AndroidPackage p = mPackages.get(packageName);
@@ -14375,6 +14379,7 @@ public class PackageManagerService extends IPackageManager.Stub
integrityVerification.putExtra(EXTRA_VERIFICATION_ID, verificationId);
integrityVerification.putExtra(EXTRA_PACKAGE_NAME, pkgLite.packageName);
integrityVerification.putExtra(EXTRA_VERSION_CODE, pkgLite.versionCode);
+ integrityVerification.putExtra(EXTRA_LONG_VERSION_CODE, pkgLite.getLongVersionCode());
populateInstallerExtras(integrityVerification);
// send to integrity component only.
@@ -20211,8 +20216,8 @@ public class PackageManagerService extends IPackageManager.Stub
// Disable any carrier apps. We do this very early in boot to prevent the apps from being
// disabled after already being started.
- CarrierAppUtils.disableCarrierAppsUntilPrivileged(mContext.getOpPackageName(), this,
- mPermissionManagerService, UserHandle.USER_SYSTEM, mContext);
+ CarrierAppUtils.disableCarrierAppsUntilPrivileged(
+ mContext.getOpPackageName(), UserHandle.USER_SYSTEM, mContext);
disableSkuSpecificApps();
@@ -23098,6 +23103,12 @@ public class PackageManagerService extends IPackageManager.Stub
}
@Override
+ public int getPackageUidInternal(String packageName, int flags, int userId) {
+ return PackageManagerService.this
+ .getPackageUidInternal(packageName, flags, userId, Process.SYSTEM_UID);
+ }
+
+ @Override
public ApplicationInfo getApplicationInfo(
String packageName, int flags, int filterCallingUid, int userId) {
return PackageManagerService.this
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index a0e6be4d9a6b..39d1a51c01de 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -20,7 +20,6 @@ import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED;
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
import static android.os.Debug.getIonHeapsSizeKb;
-import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
import static android.os.Process.getUidForPid;
import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
import static android.os.storage.VolumeInfo.TYPE_PUBLIC;
@@ -32,11 +31,8 @@ import static com.android.server.stats.pull.ProcfsMemoryUtil.forEachPid;
import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs;
import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManagerInternal;
-import android.app.AlarmManager;
-import android.app.AlarmManager.OnAlarmListener;
import android.app.AppOpsManager;
import android.app.AppOpsManager.HistoricalOps;
import android.app.AppOpsManager.HistoricalOpsRequest;
@@ -49,10 +45,7 @@ import android.app.StatsManager.PullAtomMetadata;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.UidTraffic;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -74,23 +67,14 @@ import android.os.Build;
import android.os.Bundle;
import android.os.CoolingDevice;
import android.os.Environment;
-import android.os.FileUtils;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.os.IPullAtomCallback;
-import android.os.IStatsCompanionService;
-import android.os.IStatsd;
import android.os.IStoraged;
import android.os.IThermalEventListener;
import android.os.IThermalService;
-import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StatFs;
-import android.os.StatsLogEventWrapper;
import android.os.SynchronousResultReceiver;
import android.os.SystemClock;
import android.os.SystemProperties;
@@ -134,7 +118,6 @@ import com.android.internal.os.LooperStats;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.StoragedUidIoStatsReader;
-import com.android.internal.util.DumpUtils;
import com.android.server.BinderCallsStatsService;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -156,20 +139,15 @@ import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
-import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.MissingResourceException;
-import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@@ -229,6 +207,25 @@ public class StatsPullAtomService extends SystemService {
mTelephony = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class);
+ final ConnectivityManager connectivityManager =
+ (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ // Default NetworkRequest should cover all transport types.
+ final NetworkRequest request = new NetworkRequest.Builder().build();
+ connectivityManager.registerNetworkCallback(request, new ConnectivityStatsCallback());
+
+ // Enable push notifications of throttling from vendor thermal
+ // management subsystem via thermalservice.
+ IThermalService thermalService = getIThermalService();
+ if (thermalService != null) {
+ try {
+ thermalService.registerThermalEventListener(
+ new ThermalEventListener());
+ Slog.i(TAG, "register thermal listener successfully");
+ } catch (RemoteException e) {
+ Slog.i(TAG, "failed to register thermal listener");
+ }
+ }
+
// Initialize state for CPU_TIME_PER_FREQ atom
PowerProfile powerProfile = new PowerProfile(mContext);
final int numClusters = powerProfile.getNumCpuClusters();
@@ -2896,4 +2893,29 @@ public class StatsPullAtomService extends SystemService {
BackgroundThread.getExecutor()
);
}
+
+
+ // Thermal event received from vendor thermal management subsystem
+ private static final class ThermalEventListener extends IThermalEventListener.Stub {
+ @Override
+ public void notifyThrottling(Temperature temp) {
+ StatsLog.write(StatsLog.THERMAL_THROTTLING_SEVERITY_STATE_CHANGED, temp.getType(),
+ temp.getName(), (int) (temp.getValue() * 10), temp.getStatus());
+ }
+ }
+
+ private static final class ConnectivityStatsCallback extends
+ ConnectivityManager.NetworkCallback {
+ @Override
+ public void onAvailable(Network network) {
+ StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId,
+ StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__CONNECTED);
+ }
+
+ @Override
+ public void onLost(Network network) {
+ StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId,
+ StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__DISCONNECTED);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index 0abe68f270f3..8130546e2699 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -22,6 +22,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.os.Binder;
import android.os.PatternMatcher;
import android.os.Process;
@@ -34,6 +35,7 @@ import android.webkit.WebViewProviderInfo;
import android.webkit.WebViewProviderResponse;
import com.android.internal.util.DumpUtils;
+import com.android.server.LocalServices;
import com.android.server.SystemService;
import java.io.FileDescriptor;
@@ -191,7 +193,26 @@ public class WebViewUpdateService extends SystemService {
throw new IllegalStateException("Cannot create a WebView from the SystemServer");
}
- return WebViewUpdateService.this.mImpl.waitForAndGetProvider();
+ final WebViewProviderResponse webViewProviderResponse =
+ WebViewUpdateService.this.mImpl.waitForAndGetProvider();
+ if (webViewProviderResponse.packageInfo != null) {
+ grantVisibilityToCaller(
+ webViewProviderResponse.packageInfo.packageName, Binder.getCallingUid());
+ }
+ return webViewProviderResponse;
+ }
+
+ /**
+ * Grants app visibility of the webViewPackageName to the currently bound caller.
+ * @param webViewPackageName
+ */
+ private void grantVisibilityToCaller(String webViewPackageName, int callingUid) {
+ final PackageManagerInternal pmInternal = LocalServices.getService(
+ PackageManagerInternal.class);
+ final int webviewUid = pmInternal.getPackageUidInternal(
+ webViewPackageName, 0, UserHandle.getUserId(callingUid));
+ pmInternal.grantImplicitAccess(UserHandle.getUserId(callingUid), null, webviewUid,
+ UserHandle.getAppId(callingUid));
}
/**
@@ -231,13 +252,18 @@ public class WebViewUpdateService extends SystemService {
@Override // Binder call
public String getCurrentWebViewPackageName() {
- PackageInfo pi = WebViewUpdateService.this.mImpl.getCurrentWebViewPackage();
+ PackageInfo pi = getCurrentWebViewPackage();
return pi == null ? null : pi.packageName;
}
@Override // Binder call
public PackageInfo getCurrentWebViewPackage() {
- return WebViewUpdateService.this.mImpl.getCurrentWebViewPackage();
+ final PackageInfo currentWebViewPackage =
+ WebViewUpdateService.this.mImpl.getCurrentWebViewPackage();
+ if (currentWebViewPackage != null) {
+ grantVisibilityToCaller(currentWebViewPackage.packageName, Binder.getCallingUid());
+ }
+ return currentWebViewPackage;
}
@Override // Binder call
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index d1c8448f2a4a..57865957b8d4 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1627,7 +1627,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
requestedVrComponent = (aInfo.requestedVrComponent == null) ?
null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
- lockTaskLaunchMode = getLockTaskLaunchMode(aInfo, options);
+ lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
+ if (info.applicationInfo.isPrivilegedApp()
+ && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
+ || lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
+ lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
+ }
if (options != null) {
pendingOptions = options;
@@ -1635,25 +1640,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (usageReport != null) {
appTimeTracker = new AppTimeTracker(usageReport);
}
- // Gets launch display id from options. It returns INVALID_DISPLAY if not set.
- mHandoverLaunchDisplayId = options.getLaunchDisplayId();
- }
- }
-
- static int getLockTaskLaunchMode(ActivityInfo aInfo, @Nullable ActivityOptions options) {
- int lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
- if (aInfo.applicationInfo.isPrivilegedApp()
- && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
- || lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
- lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
- }
- if (options != null) {
- final boolean useLockTask = options.getLockTaskMode();
+ final boolean useLockTask = pendingOptions.getLockTaskMode();
if (useLockTask && lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_DEFAULT) {
lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
}
+ // Gets launch display id from options. It returns INVALID_DISPLAY if not set.
+ mHandoverLaunchDisplayId = options.getLaunchDisplayId();
}
- return lockTaskLaunchMode;
}
@Override
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index d61d29d1084e..2fb0ac5fbeaa 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -52,7 +52,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.app.BlockedAppActivity;
import com.android.internal.app.HarmfulAppWarningActivity;
import com.android.internal.app.SuspendedAppActivity;
import com.android.internal.app.UnlaunchableAppActivity;
@@ -167,9 +166,6 @@ class ActivityStartInterceptor {
// no user action can undo this.
return true;
}
- if (interceptLockTaskModeViolationPackageIfNeeded()) {
- return true;
- }
if (interceptHarmfulAppIfNeeded()) {
// If the app has a "harmful app" warning associated with it, we should ask to uninstall
// before issuing the work challenge.
@@ -178,6 +174,11 @@ class ActivityStartInterceptor {
return interceptWorkProfileChallengeIfNeeded();
}
+ private boolean hasCrossProfileAnimation() {
+ return mActivityOptions != null
+ && mActivityOptions.getAnimationType() == ANIM_OPEN_CROSS_PROFILE_APPS;
+ }
+
/**
* If the activity option is the {@link ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} one,
* defer the animation until the original intent is started.
@@ -185,8 +186,7 @@ class ActivityStartInterceptor {
* @return the activity option used to start the original intent.
*/
private Bundle deferCrossProfileAppsAnimationIfNecessary() {
- if (mActivityOptions != null
- && mActivityOptions.getAnimationType() == ANIM_OPEN_CROSS_PROFILE_APPS) {
+ if (hasCrossProfileAnimation()) {
mActivityOptions = null;
return ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle();
}
@@ -255,28 +255,13 @@ class ActivityStartInterceptor {
}
final SuspendDialogInfo dialogInfo = pmi.getSuspendedDialogInfo(suspendedPackage,
suspendingPackage, mUserId);
+ final Bundle crossProfileOptions = hasCrossProfileAnimation()
+ ? ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle()
+ : null;
+ final IntentSender target = createIntentSenderForOriginalIntent(mCallingUid,
+ FLAG_IMMUTABLE);
mIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent(suspendedPackage,
- suspendingPackage, dialogInfo, deferCrossProfileAppsAnimationIfNecessary(),
- mUserId);
- mCallingPid = mRealCallingPid;
- mCallingUid = mRealCallingUid;
- mResolvedType = null;
- mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, mUserId, 0, mRealCallingUid);
- mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, null /*profilerInfo*/);
- return true;
- }
-
- private boolean interceptLockTaskModeViolationPackageIfNeeded() {
- if (mAInfo == null || mAInfo.applicationInfo == null) {
- return false;
- }
- LockTaskController controller = mService.getLockTaskController();
- String packageName = mAInfo.applicationInfo.packageName;
- int lockTaskLaunchMode = ActivityRecord.getLockTaskLaunchMode(mAInfo, mActivityOptions);
- if (controller.isActivityAllowed(mUserId, packageName, lockTaskLaunchMode)) {
- return false;
- }
- mIntent = BlockedAppActivity.createIntent(mUserId, mAInfo.applicationInfo.packageName);
+ suspendingPackage, dialogInfo, crossProfileOptions, target, mUserId);
mCallingPid = mRealCallingPid;
mCallingUid = mRealCallingUid;
mResolvedType = null;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 31b7c688d685..40a45641ab04 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3303,7 +3303,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
}
- private int sanitizeAndApplyChange(ConfigurationContainer container,
+ private int sanitizeAndApplyChange(WindowContainer container,
WindowContainerTransaction.Change change) {
if (!(container instanceof Task || container instanceof ActivityStack)) {
throw new RuntimeException("Invalid token in task transaction");
@@ -3347,13 +3347,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
}
- private int applyWindowContainerChange(ConfigurationContainer cc,
+ private int applyWindowContainerChange(WindowContainer wc,
WindowContainerTransaction.Change c) {
- int effects = sanitizeAndApplyChange(cc, c);
+ int effects = sanitizeAndApplyChange(wc, c);
Rect enterPipBounds = c.getEnterPipBounds();
if (enterPipBounds != null) {
- Task tr = (Task) cc;
+ Task tr = (Task) wc;
mStackSupervisor.updatePictureInPictureMode(tr,
enterPipBounds, true);
}
@@ -3378,17 +3378,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
while (entries.hasNext()) {
final Map.Entry<IBinder, WindowContainerTransaction.Change> entry =
entries.next();
- final ConfigurationContainer cc =
- ConfigurationContainer.RemoteToken.fromBinder(
- entry.getKey()).getContainer();
- int containerEffect = applyWindowContainerChange(cc, entry.getValue());
+ final WindowContainer wc = WindowContainer.RemoteToken.fromBinder(
+ entry.getKey()).getContainer();
+ int containerEffect = applyWindowContainerChange(wc, entry.getValue());
effects |= containerEffect;
// Lifecycle changes will trigger ensureConfig for everything.
if ((effects & TRANSACT_EFFECTS_LIFECYCLE) == 0
&& (containerEffect & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
- if (cc instanceof WindowContainer) {
- haveConfigChanges.add((WindowContainer) cc);
- }
+ haveConfigChanges.add(wc);
}
}
if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) {
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 7b23e2d383b6..9bd380a95ad0 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -39,15 +39,11 @@ import android.app.WindowConfiguration;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
-import android.os.IBinder;
import android.util.proto.ProtoOutputStream;
-import android.view.IWindowContainer;
-import android.view.SurfaceControl;
import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
import java.util.ArrayList;
/**
@@ -104,12 +100,6 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
static final int BOUNDS_CHANGE_SIZE = 1 << 1;
/**
- * Used as a unique, cross-process identifier for this Container. It also serves a minimal
- * interface to other processes.
- */
- RemoteToken mRemoteToken = null;
-
- /**
* Returns full configuration applied to this configuration container.
* This method should be used for getting settings applied in each particular level of the
* hierarchy.
@@ -629,21 +619,6 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
return mFullConfiguration.windowConfiguration.isAlwaysOnTop();
}
- /**
- * Returns {@code true} if this container is focusable. Generally, if a parent is not focusable,
- * this will not be focusable either.
- */
- boolean isFocusable() {
- // TODO(split): Move this to WindowContainer once Split-screen is based on a WindowContainer
- // like DisplayArea vs. TaskTiles.
- ConfigurationContainer parent = getParent();
- return parent == null || parent.isFocusable();
- }
-
- boolean setFocusable(boolean focusable) {
- return false;
- }
-
boolean hasChild() {
return getChildCount() > 0;
}
@@ -654,40 +629,4 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
abstract protected ConfigurationContainer getParent();
- // TODO: Consider moving to WindowContainer once hierarchies and Task/Stack are merged.
- static class RemoteToken extends IWindowContainer.Stub {
- final WeakReference<ConfigurationContainer> mWeakRef;
-
- RemoteToken(ConfigurationContainer container) {
- mWeakRef = new WeakReference<>(container);
- }
-
- ConfigurationContainer getContainer() {
- return mWeakRef.get();
- }
-
- static RemoteToken fromBinder(IBinder binder) {
- return (RemoteToken) binder;
- }
-
- @Override
- public SurfaceControl getLeash() {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder(128);
- sb.append("RemoteToken{");
- sb.append(Integer.toHexString(System.identityHashCode(this)));
- sb.append(' ');
- sb.append(mWeakRef.get());
- sb.append('}');
- return sb.toString();
- }
- }
-
- RemoteToken getRemoteToken() {
- return mRemoteToken;
- }
}
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index 33b0453a25ee..02413bb48518 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -23,8 +23,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Context.DEVICE_POLICY_SERVICE;
import static android.content.Context.STATUS_BAR_SERVICE;
import static android.content.Intent.ACTION_CALL_EMERGENCY;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_CURRENT;
import static android.telecom.TelecomManager.EMERGENCY_DIALER_COMPONENT;
@@ -341,20 +339,6 @@ public class LockTaskController {
& DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD) != 0;
}
- boolean isActivityAllowed(int userId, String packageName, int lockTaskLaunchMode) {
- if (mLockTaskModeState != LOCK_TASK_MODE_LOCKED) {
- return true;
- }
- switch (lockTaskLaunchMode) {
- case LOCK_TASK_LAUNCH_MODE_ALWAYS:
- return true;
- case LOCK_TASK_LAUNCH_MODE_NEVER:
- return false;
- default:
- }
- return isPackageWhitelisted(userId, packageName);
- }
-
private boolean isEmergencyCallTask(Task task) {
final Intent intent = task.intent;
if (intent == null) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 917b437c8244..5ecbec4c1180 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static android.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ActivityTaskManager.RESIZE_MODE_FORCED;
import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
@@ -496,7 +495,7 @@ class Task extends WindowContainer<WindowContainer> {
}
class TaskToken extends RemoteToken {
- TaskToken(ConfigurationContainer container) {
+ TaskToken(WindowContainer container) {
super(container);
}
@@ -2724,6 +2723,7 @@ class Task extends WindowContainer<WindowContainer> {
boolean[] foundTop = { false };
final PooledConsumer c = PooledLambda.obtainConsumer(Task::getMaxVisibleBounds,
PooledLambda.__(ActivityRecord.class), out, foundTop);
+ forAllActivities(c);
c.recycle();
if (foundTop[0]) {
return;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 4cb5de44bef0..10d6823c850f 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -343,6 +343,7 @@ class TaskSnapshotController {
builder.setPixelFormat(pixelFormat);
builder.setIsTranslucent(isTranslucent);
builder.setOrientation(activity.getTask().getConfiguration().orientation);
+ builder.setRotation(activity.getTask().getDisplayContent().getRotation());
builder.setWindowingMode(task.getWindowingMode());
builder.setSystemUiVisibility(getSystemUiVisibility(task));
return true;
@@ -492,7 +493,8 @@ class TaskSnapshotController {
return new TaskSnapshot(
System.currentTimeMillis() /* id */,
topChild.mActivityComponent, hwBitmap.createGraphicBufferHandle(),
- hwBitmap.getColorSpace(), topChild.getTask().getConfiguration().orientation,
+ hwBitmap.getColorSpace(), mainWindow.getConfiguration().orientation,
+ mainWindow.getWindowConfiguration().getRotation(),
getInsets(mainWindow), ActivityManager.isLowRamDeviceStatic() /* reduced */,
mFullSnapshotScale, false /* isRealSnapshot */, task.getWindowingMode(),
getSystemUiVisibility(task), false);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
index 22c1ea59d176..6e9986ffd411 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
@@ -102,8 +102,8 @@ class TaskSnapshotLoader {
// For legacy snapshots, restore the scale based on the reduced resolution state
final float legacyScale = reducedResolution ? mPersister.getReducedScale() : 1f;
final float scale = Float.compare(proto.scale, 0f) != 0 ? proto.scale : legacyScale;
- return new TaskSnapshot(proto.id, topActivityComponent, buffer,
- hwBitmap.getColorSpace(), proto.orientation,
+ return new TaskSnapshot(proto.id, topActivityComponent, buffer, hwBitmap.getColorSpace(),
+ proto.orientation, proto.rotation,
new Rect(proto.insetLeft, proto.insetTop, proto.insetRight, proto.insetBottom),
reducedResolution, scale, proto.isRealSnapshot, proto.windowingMode,
proto.systemUiVisibility, proto.isTranslucent);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 828775a4b934..ee5098b6c699 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -342,6 +342,7 @@ class TaskSnapshotPersister {
boolean writeProto() {
final TaskSnapshotProto proto = new TaskSnapshotProto();
proto.orientation = mSnapshot.getOrientation();
+ proto.rotation = mSnapshot.getRotation();
proto.insetLeft = mSnapshot.getContentInsets().left;
proto.insetTop = mSnapshot.getContentInsets().top;
proto.insetRight = mSnapshot.getContentInsets().right;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 1c876d9cc02f..0ab5f91f0ce9 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -61,6 +61,7 @@ import android.util.Pools;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo;
+import android.view.IWindowContainer;
import android.view.MagnificationSpec;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
@@ -75,6 +76,7 @@ import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.Animatable;
import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
@@ -249,6 +251,12 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
private boolean mIsFocusable = true;
+ /**
+ * Used as a unique, cross-process identifier for this Container. It also serves a minimal
+ * interface to other processes.
+ */
+ RemoteToken mRemoteToken = null;
+
WindowContainer(WindowManagerService wms) {
mWmService = wms;
mPendingTransaction = wms.mTransactionFactory.get();
@@ -860,13 +868,16 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
return false;
}
- @Override
+ /**
+ * Returns {@code true} if this container is focusable. Generally, if a parent is not focusable,
+ * this will not be focusable either.
+ */
boolean isFocusable() {
- return super.isFocusable() && mIsFocusable;
+ final WindowContainer parent = getParent();
+ return (parent == null || parent.isFocusable()) && mIsFocusable;
}
/** Set whether this container or its children can be focusable */
- @Override
boolean setFocusable(boolean focusable) {
if (mIsFocusable == focusable) {
return false;
@@ -2259,4 +2270,40 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
ActivityRecord asActivityRecord() {
return null;
}
+
+ RemoteToken getRemoteToken() {
+ return mRemoteToken;
+ }
+
+ static class RemoteToken extends IWindowContainer.Stub {
+ final WeakReference<WindowContainer> mWeakRef;
+
+ RemoteToken(WindowContainer container) {
+ mWeakRef = new WeakReference<>(container);
+ }
+
+ WindowContainer getContainer() {
+ return mWeakRef.get();
+ }
+
+ static RemoteToken fromBinder(IBinder binder) {
+ return (RemoteToken) binder;
+ }
+
+ @Override
+ public SurfaceControl getLeash() {
+ throw new RuntimeException("Not implemented");
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("RemoteToken{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(' ');
+ sb.append(mWeakRef.get());
+ sb.append('}');
+ return sb.toString();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8d4ad28972e9..27de95a84ab6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -122,6 +122,7 @@ import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityManagerInternal;
@@ -2996,7 +2997,13 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- void showGlobalActions() {
+ @RequiresPermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW)
+ @Override
+ public void showGlobalActions() {
+ if (!checkCallingPermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW,
+ "showGlobalActions()")) {
+ throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+ }
mPolicy.showGlobalActions();
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 82f5d50b41c7..d7ea2f53c286 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -180,6 +180,7 @@ import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.location.LocationManager;
+import android.location.LocationManagerInternal;
import android.media.AudioManager;
import android.media.IAudioService;
import android.net.ConnectivityManager;
@@ -2096,6 +2097,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return mContext.getSystemService(LocationManager.class);
}
+ LocationManagerInternal getLocationManagerInternal() {
+ return LocalServices.getService(LocationManagerInternal.class);
+ }
+
IWindowManager getIWindowManager() {
return IWindowManager.Stub
.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
@@ -11553,6 +11558,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
+ public void requestSetLocationProviderAllowed(ComponentName who, String provider,
+ boolean providerAllowed) {
+ Objects.requireNonNull(who, "ComponentName is null");
+ enforceDeviceOwner(who);
+
+ mInjector.binderWithCleanCallingIdentity(
+ () -> mInjector.getLocationManagerInternal().requestSetProviderAllowed(provider,
+ providerAllowed));
+ }
+
+ @Override
public boolean setTime(ComponentName who, long millis) {
Objects.requireNonNull(who, "ComponentName is null in setTime");
enforceDeviceOwnerOrProfileOwnerOnOrganizationOwnedDevice(who);
diff --git a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
index a6af9a99788f..9a633931017e 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
@@ -57,7 +57,6 @@ import android.os.Handler;
import android.os.Message;
import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
import com.android.internal.R;
import com.android.server.LocalServices;
@@ -68,6 +67,7 @@ import com.android.server.testutils.TestUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
@@ -81,7 +81,7 @@ import java.util.List;
import java.util.Map;
/** Unit test for {@link com.android.server.integrity.AppIntegrityManagerServiceImpl} */
-@RunWith(AndroidJUnit4.class)
+@RunWith(JUnit4.class)
public class AppIntegrityManagerServiceImplTest {
private static final String TEST_APP_PATH =
"/data/local/tmp/AppIntegrityManagerServiceTestApp.apk";
@@ -91,8 +91,10 @@ public class AppIntegrityManagerServiceImplTest {
private static final String TEST_FRAMEWORK_PACKAGE = "com.android.frameworks.servicestests";
private static final String PACKAGE_NAME = "com.test.app";
- private static final int VERSION_CODE = 100;
+
+ private static final long VERSION_CODE = 100;
private static final String INSTALLER = "com.long.random.test.installer.name";
+
// These are obtained by running the test and checking logcat.
private static final String APP_CERT =
"301AA3CB081134501C45F1422ABC66C24224FD5DED5FDC8F17E697176FD866AA";
@@ -108,7 +110,8 @@ public class AppIntegrityManagerServiceImplTest {
"play_store_cert";
private static final String ADB_CERT = "";
- @org.junit.Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @org.junit.Rule
+ public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock PackageManagerInternal mPackageManagerInternal;
@Mock Context mMockContext;
@@ -173,7 +176,8 @@ public class AppIntegrityManagerServiceImplTest {
makeUsSystemApp();
Rule rule =
new Rule(
- new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+ new AtomicFormula.BooleanAtomicFormula(
+ AtomicFormula.PRE_INSTALLED, true),
Rule.DENY);
TestUtils.assertExpectException(
SecurityException.class,
@@ -191,7 +195,8 @@ public class AppIntegrityManagerServiceImplTest {
whitelistUsAsRuleProvider();
Rule rule =
new Rule(
- new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+ new AtomicFormula.BooleanAtomicFormula(
+ AtomicFormula.PRE_INSTALLED, true),
Rule.DENY);
TestUtils.assertExpectException(
SecurityException.class,
@@ -210,7 +215,8 @@ public class AppIntegrityManagerServiceImplTest {
makeUsSystemApp();
Rule rule =
new Rule(
- new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+ new AtomicFormula.BooleanAtomicFormula(
+ AtomicFormula.PRE_INSTALLED, true),
Rule.DENY);
// no SecurityException
@@ -447,7 +453,7 @@ public class AppIntegrityManagerServiceImplTest {
intent.putExtra(
EXTRA_VERIFICATION_INSTALLER_UID,
mMockContext.getPackageManager().getPackageUid(installer, /* flags= */ 0));
- intent.putExtra(Intent.EXTRA_VERSION_CODE, VERSION_CODE);
+ intent.putExtra(Intent.EXTRA_LONG_VERSION_CODE, VERSION_CODE);
return intent;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java b/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java
index a1810b971b09..86daf69fb2d9 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/IntegrityFileManagerTest.java
@@ -22,7 +22,7 @@ import static com.google.common.truth.Truth.assertThat;
import android.content.integrity.AppInstallMetadata;
import android.content.integrity.AtomicFormula;
-import android.content.integrity.AtomicFormula.IntAtomicFormula;
+import android.content.integrity.AtomicFormula.LongAtomicFormula;
import android.content.integrity.AtomicFormula.StringAtomicFormula;
import android.content.integrity.CompoundFormula;
import android.content.integrity.Rule;
@@ -116,7 +116,8 @@ public class IntegrityFileManagerTest {
Rule packageCertRule = getAppCertificateIndexedRule(packageCert);
Rule versionCodeRule =
new Rule(
- new IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.LE, version),
+ new LongAtomicFormula(
+ AtomicFormula.VERSION_CODE, AtomicFormula.EQ, version),
Rule.DENY);
Rule randomRule =
new Rule(
@@ -127,9 +128,9 @@ public class IntegrityFileManagerTest {
AtomicFormula.PACKAGE_NAME,
"abc",
/* isHashedValue= */ false),
- new IntAtomicFormula(
+ new LongAtomicFormula(
AtomicFormula.VERSION_CODE,
- AtomicFormula.LE,
+ AtomicFormula.EQ,
version))),
Rule.DENY);
@@ -201,21 +202,22 @@ public class IntegrityFileManagerTest {
private Rule getPackageNameIndexedRule(String packageName) {
return new Rule(
new StringAtomicFormula(
- AtomicFormula.PACKAGE_NAME, packageName, /* isHashedValue= */ false),
+ AtomicFormula.PACKAGE_NAME, packageName, /* isHashedValue= */false),
Rule.DENY);
}
private Rule getAppCertificateIndexedRule(String appCertificate) {
return new Rule(
new StringAtomicFormula(
- AtomicFormula.APP_CERTIFICATE, appCertificate, /* isHashedValue= */ false),
+ AtomicFormula.APP_CERTIFICATE,
+ appCertificate, /* isHashedValue= */ false),
Rule.DENY);
}
private Rule getInstallerCertificateRule(String installerCert) {
return new Rule(
new StringAtomicFormula(
- AtomicFormula.INSTALLER_NAME, installerCert, /* isHashedValue= */ false),
+ AtomicFormula.INSTALLER_NAME, installerCert, /* isHashedValue= */false),
Rule.DENY);
}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java
index d3864878d4b2..99157024bb66 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluationEngineTest.java
@@ -50,7 +50,8 @@ public class RuleEvaluationEngineTest {
private static final String RANDOM_INSTALLER = "random";
private static final String RANDOM_INSTALLER_CERT = "random_cert";
- @Mock private IntegrityFileManager mIntegrityFileManager;
+ @Mock
+ private IntegrityFileManager mIntegrityFileManager;
private RuleEvaluationEngine mEngine;
@@ -70,29 +71,29 @@ public class RuleEvaluationEngineTest {
assertEquals(
IntegrityCheckResult.Effect.ALLOW,
mEngine.evaluate(
- getAppInstallMetadataBuilder()
- .setInstallerName(INSTALLER_1)
- .setInstallerCertificate(INSTALLER_1_CERT)
- .build(),
- allowedInstallers)
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_1)
+ .setInstallerCertificate(INSTALLER_1_CERT)
+ .build(),
+ allowedInstallers)
.getEffect());
assertEquals(
IntegrityCheckResult.Effect.ALLOW,
mEngine.evaluate(
- getAppInstallMetadataBuilder()
- .setInstallerName(INSTALLER_2)
- .setInstallerCertificate(INSTALLER_2_CERT)
- .build(),
- allowedInstallers)
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_2)
+ .setInstallerCertificate(INSTALLER_2_CERT)
+ .build(),
+ allowedInstallers)
.getEffect());
assertEquals(
IntegrityCheckResult.Effect.ALLOW,
mEngine.evaluate(
- getAppInstallMetadataBuilder()
- .setInstallerName(RANDOM_INSTALLER)
- .setInstallerCertificate(RANDOM_INSTALLER_CERT)
- .build(),
- allowedInstallers)
+ getAppInstallMetadataBuilder()
+ .setInstallerName(RANDOM_INSTALLER)
+ .setInstallerCertificate(RANDOM_INSTALLER_CERT)
+ .build(),
+ allowedInstallers)
.getEffect());
}
@@ -104,38 +105,38 @@ public class RuleEvaluationEngineTest {
assertEquals(
IntegrityCheckResult.Effect.ALLOW,
mEngine.evaluate(
- getAppInstallMetadataBuilder()
- .setInstallerName(INSTALLER_1)
- .setInstallerCertificate(INSTALLER_1_CERT)
- .build(),
- allowedInstallers)
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_1)
+ .setInstallerCertificate(INSTALLER_1_CERT)
+ .build(),
+ allowedInstallers)
.getEffect());
assertEquals(
IntegrityCheckResult.Effect.DENY,
mEngine.evaluate(
- getAppInstallMetadataBuilder()
- .setInstallerName(RANDOM_INSTALLER)
- .setInstallerCertificate(INSTALLER_1_CERT)
- .build(),
- allowedInstallers)
+ getAppInstallMetadataBuilder()
+ .setInstallerName(RANDOM_INSTALLER)
+ .setInstallerCertificate(INSTALLER_1_CERT)
+ .build(),
+ allowedInstallers)
.getEffect());
assertEquals(
IntegrityCheckResult.Effect.DENY,
mEngine.evaluate(
- getAppInstallMetadataBuilder()
- .setInstallerName(INSTALLER_1)
- .setInstallerCertificate(RANDOM_INSTALLER_CERT)
- .build(),
- allowedInstallers)
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_1)
+ .setInstallerCertificate(RANDOM_INSTALLER_CERT)
+ .build(),
+ allowedInstallers)
.getEffect());
assertEquals(
IntegrityCheckResult.Effect.DENY,
mEngine.evaluate(
- getAppInstallMetadataBuilder()
- .setInstallerName(RANDOM_INSTALLER)
- .setInstallerCertificate(RANDOM_INSTALLER_CERT)
- .build(),
- allowedInstallers)
+ getAppInstallMetadataBuilder()
+ .setInstallerName(RANDOM_INSTALLER)
+ .setInstallerCertificate(RANDOM_INSTALLER_CERT)
+ .build(),
+ allowedInstallers)
.getEffect());
}
@@ -149,38 +150,38 @@ public class RuleEvaluationEngineTest {
assertEquals(
IntegrityCheckResult.Effect.ALLOW,
mEngine.evaluate(
- getAppInstallMetadataBuilder()
- .setInstallerName(INSTALLER_1)
- .setInstallerCertificate(INSTALLER_1_CERT)
- .build(),
- allowedInstallers)
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_1)
+ .setInstallerCertificate(INSTALLER_1_CERT)
+ .build(),
+ allowedInstallers)
.getEffect());
assertEquals(
IntegrityCheckResult.Effect.ALLOW,
mEngine.evaluate(
- getAppInstallMetadataBuilder()
- .setInstallerName(INSTALLER_2)
- .setInstallerCertificate(INSTALLER_2_CERT)
- .build(),
- allowedInstallers)
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_2)
+ .setInstallerCertificate(INSTALLER_2_CERT)
+ .build(),
+ allowedInstallers)
.getEffect());
assertEquals(
IntegrityCheckResult.Effect.DENY,
mEngine.evaluate(
- getAppInstallMetadataBuilder()
- .setInstallerName(INSTALLER_1)
- .setInstallerCertificate(INSTALLER_2_CERT)
- .build(),
- allowedInstallers)
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_1)
+ .setInstallerCertificate(INSTALLER_2_CERT)
+ .build(),
+ allowedInstallers)
.getEffect());
assertEquals(
IntegrityCheckResult.Effect.DENY,
mEngine.evaluate(
- getAppInstallMetadataBuilder()
- .setInstallerName(INSTALLER_2)
- .setInstallerCertificate(INSTALLER_1_CERT)
- .build(),
- allowedInstallers)
+ getAppInstallMetadataBuilder()
+ .setInstallerName(INSTALLER_2)
+ .setInstallerCertificate(INSTALLER_1_CERT)
+ .build(),
+ allowedInstallers)
.getEffect());
}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java
index eda2b701fd8d..629fd14befcc 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java
@@ -19,10 +19,11 @@ package com.android.server.integrity.engine;
import static com.android.server.integrity.model.IntegrityCheckResult.Effect.ALLOW;
import static com.android.server.integrity.model.IntegrityCheckResult.Effect.DENY;
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
import android.content.integrity.AppInstallMetadata;
import android.content.integrity.AtomicFormula;
+import android.content.integrity.AtomicFormula.LongAtomicFormula;
import android.content.integrity.AtomicFormula.StringAtomicFormula;
import android.content.integrity.CompoundFormula;
import android.content.integrity.Rule;
@@ -57,7 +58,7 @@ public class RuleEvaluatorTest {
IntegrityCheckResult result = RuleEvaluator.evaluateRules(rules, APP_INSTALL_METADATA);
- assertEquals(ALLOW, result.getEffect());
+ assertThat(result.getEffect()).isEqualTo(ALLOW);
}
@Test
@@ -73,7 +74,7 @@ public class RuleEvaluatorTest {
IntegrityCheckResult result =
RuleEvaluator.evaluateRules(Collections.singletonList(rule1), APP_INSTALL_METADATA);
- assertEquals(ALLOW, result.getEffect());
+ assertThat(result.getEffect()).isEqualTo(ALLOW);
}
@Test
@@ -96,8 +97,8 @@ public class RuleEvaluatorTest {
IntegrityCheckResult result =
RuleEvaluator.evaluateRules(Arrays.asList(rule1, rule2), APP_INSTALL_METADATA);
- assertEquals(DENY, result.getEffect());
- assertEquals(rule1, result.getRule());
+ assertThat(result.getEffect()).isEqualTo(DENY);
+ assertThat(result.getRule()).isEqualTo(rule1);
}
@Test
@@ -126,8 +127,8 @@ public class RuleEvaluatorTest {
IntegrityCheckResult result =
RuleEvaluator.evaluateRules(Arrays.asList(rule1, rule2), APP_INSTALL_METADATA);
- assertEquals(DENY, result.getEffect());
- assertEquals(rule1, result.getRule());
+ assertThat(result.getEffect()).isEqualTo(DENY);
+ assertThat(result.getRule()).isEqualTo(rule1);
}
@Test
@@ -145,23 +146,23 @@ public class RuleEvaluatorTest {
IntegrityCheckResult result =
RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
- assertEquals(DENY, result.getEffect());
- assertEquals(rule, result.getRule());
+ assertThat(result.getEffect()).isEqualTo(DENY);
+ assertThat(result.getRule()).isEqualTo(rule);
}
@Test
public void testEvaluateRules_ruleWithIntegerOperators_deny() {
Rule rule =
new Rule(
- new AtomicFormula.IntAtomicFormula(
- AtomicFormula.VERSION_CODE, AtomicFormula.GT, 1),
+ new LongAtomicFormula(AtomicFormula.VERSION_CODE,
+ AtomicFormula.GT, 1),
Rule.DENY);
IntegrityCheckResult result =
RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
- assertEquals(DENY, result.getEffect());
- assertEquals(rule, result.getRule());
+ assertThat(result.getEffect()).isEqualTo(DENY);
+ assertThat(result.getRule()).isEqualTo(rule);
}
@Test
@@ -183,8 +184,8 @@ public class RuleEvaluatorTest {
IntegrityCheckResult result =
RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
- assertEquals(DENY, result.getEffect());
- assertEquals(rule, result.getRule());
+ assertThat(result.getEffect()).isEqualTo(DENY);
+ assertThat(result.getRule()).isEqualTo(rule);
}
@Test
@@ -206,7 +207,7 @@ public class RuleEvaluatorTest {
IntegrityCheckResult result =
RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
- assertEquals(DENY, result.getEffect());
+ assertThat(result.getEffect()).isEqualTo(DENY);
}
@Test
@@ -230,7 +231,7 @@ public class RuleEvaluatorTest {
IntegrityCheckResult result =
RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
- assertEquals(DENY, result.getEffect());
+ assertThat(result.getEffect()).isEqualTo(DENY);
}
@Test
@@ -259,7 +260,7 @@ public class RuleEvaluatorTest {
IntegrityCheckResult result =
RuleEvaluator.evaluateRules(Arrays.asList(rule1, rule2), APP_INSTALL_METADATA);
- assertEquals(ALLOW, result.getEffect());
- assertEquals(rule1, result.getRule());
+ assertThat(result.getEffect()).isEqualTo(ALLOW);
+ assertThat(result.getRule()).isEqualTo(rule1);
}
-}
+} \ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/integrity/parser/BinaryFileOperationsTest.java b/services/tests/servicestests/src/com/android/server/integrity/parser/BinaryFileOperationsTest.java
index cfa1de371e8c..723b6c5af451 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/parser/BinaryFileOperationsTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/parser/BinaryFileOperationsTest.java
@@ -26,7 +26,8 @@ import static com.android.server.integrity.utils.TestUtils.getValueBits;
import static com.google.common.truth.Truth.assertThat;
-import com.android.server.integrity.IntegrityUtils;
+import android.content.integrity.IntegrityUtils;
+
import com.android.server.integrity.model.BitInputStream;
import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java
index e0b2e2257ee4..38cf562f8c5b 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java
@@ -36,10 +36,9 @@ import static com.google.common.truth.Truth.assertThat;
import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
+import android.content.integrity.IntegrityUtils;
import android.content.integrity.Rule;
-import com.android.server.integrity.IntegrityUtils;
-
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -345,7 +344,7 @@ public class RuleBinaryParserTest {
+ ATOMIC_FORMULA_START_BITS
+ VERSION_CODE
+ EQ
- + getBits(versionCode, /* numOfBits= */ 32)
+ + getBits(versionCode, /* numOfBits= */ 64)
+ DENY
+ END_BIT;
byte[] ruleBytes = getBytes(ruleBits);
@@ -356,7 +355,7 @@ public class RuleBinaryParserTest {
RuleParser binaryParser = new RuleBinaryParser();
Rule expectedRule =
new Rule(
- new AtomicFormula.IntAtomicFormula(
+ new AtomicFormula.LongAtomicFormula(
AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1),
Rule.DENY);
@@ -384,7 +383,8 @@ public class RuleBinaryParserTest {
RuleParser binaryParser = new RuleBinaryParser();
Rule expectedRule =
new Rule(
- new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+ new AtomicFormula.BooleanAtomicFormula(
+ AtomicFormula.PRE_INSTALLED, true),
Rule.DENY);
List<Rule> rules = binaryParser.parse(rule.array());
@@ -400,7 +400,7 @@ public class RuleBinaryParserTest {
+ ATOMIC_FORMULA_START_BITS
+ VERSION_CODE
+ EQ
- + getBits(versionCode, /* numOfBits= */ 32)
+ + getBits(versionCode, /* numOfBits= */ 64)
+ DENY;
byte[] ruleBytes = getBytes(ruleBits);
ByteBuffer rule =
@@ -488,7 +488,7 @@ public class RuleBinaryParserTest {
+ ATOMIC_FORMULA_START_BITS
+ VERSION_CODE
+ INVALID_OPERATOR
- + getBits(versionCode, /* numOfBits= */ 32)
+ + getBits(versionCode, /* numOfBits= */ 64)
+ COMPOUND_FORMULA_END_BITS
+ DENY
+ END_BIT;
diff --git a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java
index 0f0dee924e29..c57136c1acab 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleXmlParserTest.java
@@ -46,15 +46,15 @@ public class RuleXmlParserTest {
String ruleXmlCompoundFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
- /* closed= */ false)
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
+ /* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
+ "</OF>"
+ "</R>"
+ "</RL>";
@@ -83,15 +83,15 @@ public class RuleXmlParserTest {
String ruleXmlCompoundFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
- /* closed= */ false)
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</OF>"
+ "</R>"
+ "</RL>";
@@ -123,17 +123,17 @@ public class RuleXmlParserTest {
String ruleXmlCompoundFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
- /* closed= */ false)
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ generateTagWithAttribute(
- /* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
+ /* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
+ "</OF>"
+ "</R>"
+ "</RL>";
@@ -168,17 +168,17 @@ public class RuleXmlParserTest {
String ruleXmlCompoundFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(CompoundFormula.OR)),
- /* closed= */ false)
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.OR)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ generateTagWithAttribute(
- /* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
+ /* tag= */ "AF", appCertificateAttrs, /* closed= */ true)
+ "</OF>"
+ "</R>"
+ "</RL>";
@@ -211,15 +211,15 @@ public class RuleXmlParserTest {
String ruleXmlCompoundFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
- /* closed= */ false)
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</OF>"
+ "</R>"
+ "</RL>";
@@ -252,17 +252,17 @@ public class RuleXmlParserTest {
String ruleXmlCompoundFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
- /* closed= */ false)
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ generateTagWithAttribute(
- /* tag= */ "AF", versionCodeAttrs, /* closed= */ true)
+ /* tag= */ "AF", versionCodeAttrs, /* closed= */ true)
+ "</OF>"
+ "</R>"
+ "</RL>";
@@ -283,15 +283,15 @@ public class RuleXmlParserTest {
String ruleXmlCompoundFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
- /* closed= */ false)
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</OF>"
+ "</R>"
+ "</RL>";
@@ -311,15 +311,15 @@ public class RuleXmlParserTest {
String ruleXmlCompoundFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", "INVALID_EFFECT"),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", "INVALID_EFFECT"),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
- /* closed= */ false)
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</OF>"
+ "</R>"
+ "</RL>";
@@ -339,17 +339,17 @@ public class RuleXmlParserTest {
String ruleXmlCompoundFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
- /* closed= */ false)
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "InvalidAtomicFormula",
- packageNameAttrs,
- /* closed= */ true)
+ /* tag= */ "InvalidAtomicFormula",
+ packageNameAttrs,
+ /* closed= */ true)
+ "</OF>"
+ "</R>"
+ "</RL>";
@@ -369,11 +369,11 @@ public class RuleXmlParserTest {
String ruleXmlAtomicFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -399,17 +399,17 @@ public class RuleXmlParserTest {
String ruleXmlAtomicFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", versionCodeAttrs, /* closed= */ true)
+ /* tag= */ "AF", versionCodeAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
Rule expectedRule =
new Rule(
- new AtomicFormula.IntAtomicFormula(
+ new AtomicFormula.LongAtomicFormula(
AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1),
Rule.DENY);
@@ -426,17 +426,18 @@ public class RuleXmlParserTest {
String ruleXmlAtomicFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", preInstalledAttrs, /* closed= */ true)
+ /* tag= */ "AF", preInstalledAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
Rule expectedRule =
new Rule(
- new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+ new AtomicFormula.BooleanAtomicFormula(
+ AtomicFormula.PRE_INSTALLED, true),
Rule.DENY);
List<Rule> rules = xmlParser.parse(ruleXmlAtomicFormula.getBytes(StandardCharsets.UTF_8));
@@ -452,11 +453,11 @@ public class RuleXmlParserTest {
String ruleXmlAtomicFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -481,11 +482,11 @@ public class RuleXmlParserTest {
String ruleXmlAtomicFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -504,11 +505,11 @@ public class RuleXmlParserTest {
String ruleXmlAtomicFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("BadEffect", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("BadEffect", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -526,16 +527,16 @@ public class RuleXmlParserTest {
String ruleXmlCompoundFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "OF",
- Collections.singletonMap(
- "BadConnector", String.valueOf(CompoundFormula.NOT)),
- /* closed= */ false)
+ /* tag= */ "OF",
+ Collections.singletonMap(
+ "BadConnector", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</OF>"
+ "</R>"
+ "</RL>";
@@ -555,11 +556,11 @@ public class RuleXmlParserTest {
String ruleXmlAtomicFormula =
"<RL>"
+ generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ "</R>"
+ "</RL>";
RuleParser xmlParser = new RuleXmlParser();
@@ -577,15 +578,15 @@ public class RuleXmlParserTest {
atomicFormulaAttrs.put("V", "com.app.test");
String ruleXmlWithNoRuleList =
generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
- /* closed= */ false)
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
+ /* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
+ "</OF>"
+ "</R>";
RuleParser xmlParser = new RuleXmlParser();
@@ -603,15 +604,15 @@ public class RuleXmlParserTest {
atomicFormulaAttrs.put("V", "com.app.test");
String ruleXmlWithNoRuleList =
generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "OF",
- Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
- /* closed= */ false)
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.NOT)),
+ /* closed= */ false)
+ generateTagWithAttribute(
- /* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
+ /* tag= */ "AF", atomicFormulaAttrs, /* closed= */ true)
+ "</OF>"
+ "</R>";
RuleParser xmlParser = new RuleXmlParser();
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java
index e5cbeee2860d..f3da286585fd 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleBinarySerializerTest.java
@@ -42,13 +42,12 @@ import static com.google.common.truth.Truth.assertThat;
import android.content.integrity.AppInstallMetadata;
import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
+import android.content.integrity.IntegrityUtils;
import android.content.integrity.Rule;
import androidx.annotation.NonNull;
-import com.android.server.integrity.IntegrityUtils;
-
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -424,11 +423,12 @@ public class RuleBinarySerializerTest {
@Test
public void testBinaryString_serializeValidAtomicFormula_integerValue() throws Exception {
- int versionCode = 1;
+ long versionCode = 1;
Rule rule =
new Rule(
- new AtomicFormula.IntAtomicFormula(
- AtomicFormula.VERSION_CODE, AtomicFormula.EQ, versionCode),
+ new AtomicFormula.LongAtomicFormula(
+ AtomicFormula.VERSION_CODE, AtomicFormula.EQ,
+ versionCode),
Rule.DENY);
RuleSerializer binarySerializer = new RuleBinarySerializer();
String expectedBits =
@@ -436,7 +436,7 @@ public class RuleBinarySerializerTest {
+ ATOMIC_FORMULA_START_BITS
+ VERSION_CODE
+ EQ
- + getBits(versionCode, /* numOfBits= */ 32)
+ + getBits(versionCode, /* numOfBits= */ 64)
+ DENY
+ END_BIT;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
@@ -456,7 +456,8 @@ public class RuleBinarySerializerTest {
String preInstalled = "1";
Rule rule =
new Rule(
- new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+ new AtomicFormula.BooleanAtomicFormula(
+ AtomicFormula.PRE_INSTALLED, true),
Rule.DENY);
RuleSerializer binarySerializer = new RuleBinarySerializer();
String expectedBits =
@@ -481,7 +482,7 @@ public class RuleBinarySerializerTest {
@Test
public void testBinaryString_serializeInvalidFormulaType() throws Exception {
- Formula invalidFormula = getInvalidFormula();
+ IntegrityFormula invalidFormula = getInvalidFormula();
Rule rule = new Rule(invalidFormula, Rule.DENY);
RuleSerializer binarySerializer = new RuleBinarySerializer();
@@ -858,16 +859,16 @@ public class RuleBinarySerializerTest {
+ END_BIT;
}
- private static Formula getInvalidFormula() {
- return new Formula() {
+ private static IntegrityFormula getInvalidFormula() {
+ return new AtomicFormula(0) {
@Override
- public boolean isSatisfied(AppInstallMetadata appInstallMetadata) {
- return false;
+ public int getTag() {
+ return 0;
}
@Override
- public int getTag() {
- return 0;
+ public boolean matches(AppInstallMetadata appInstallMetadata) {
+ return false;
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java
index 1674422f3af9..038ab7ff0c35 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleIndexingDetailsIdentifierTest.java
@@ -27,7 +27,7 @@ import static com.google.common.truth.Truth.assertThat;
import android.content.integrity.AppInstallMetadata;
import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
import android.content.integrity.Rule;
import androidx.annotation.NonNull;
@@ -71,9 +71,11 @@ public class RuleIndexingDetailsIdentifierTest {
SAMPLE_INSTALLER_CERTIFICATE,
/* isHashedValue= */ false);
private static final AtomicFormula ATOMIC_FORMULA_WITH_VERSION_CODE =
- new AtomicFormula.IntAtomicFormula(AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 12);
+ new AtomicFormula.LongAtomicFormula(AtomicFormula.VERSION_CODE,
+ AtomicFormula.EQ, 12);
private static final AtomicFormula ATOMIC_FORMULA_WITH_ISPREINSTALLED =
- new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, /* booleanValue= */
+ new AtomicFormula.BooleanAtomicFormula(
+ AtomicFormula.PRE_INSTALLED, /* booleanValue= */
true);
@@ -284,16 +286,16 @@ public class RuleIndexingDetailsIdentifierTest {
Rule.DENY);
}
- private Formula getInvalidFormula() {
- return new Formula() {
+ private IntegrityFormula getInvalidFormula() {
+ return new AtomicFormula(0) {
@Override
- public boolean isSatisfied(AppInstallMetadata appInstallMetadata) {
- return false;
+ public int getTag() {
+ return 4;
}
@Override
- public int getTag() {
- return 4;
+ public boolean matches(AppInstallMetadata appInstallMetadata) {
+ return false;
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
index ff7722c07d29..6558cd538638 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
@@ -23,7 +23,7 @@ import static org.junit.Assert.assertEquals;
import android.content.integrity.AppInstallMetadata;
import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
-import android.content.integrity.Formula;
+import android.content.integrity.IntegrityFormula;
import android.content.integrity.Rule;
import androidx.annotation.NonNull;
@@ -328,7 +328,7 @@ public class RuleXmlSerializerTest {
public void testXmlString_serializeValidAtomicFormula_integerValue() throws Exception {
Rule rule =
new Rule(
- new AtomicFormula.IntAtomicFormula(
+ new AtomicFormula.LongAtomicFormula(
AtomicFormula.VERSION_CODE, AtomicFormula.EQ, 1),
Rule.DENY);
RuleSerializer xmlSerializer = new RuleXmlSerializer();
@@ -384,7 +384,7 @@ public class RuleXmlSerializerTest {
@Test
public void testXmlString_serializeInvalidFormulaType() throws Exception {
- Formula invalidFormula = getInvalidFormula();
+ IntegrityFormula invalidFormula = getInvalidFormula();
Rule rule = new Rule(invalidFormula, Rule.DENY);
RuleSerializer xmlSerializer = new RuleXmlSerializer();
@@ -530,16 +530,16 @@ public class RuleXmlSerializerTest {
+ "</R>";
}
- private Formula getInvalidFormula() {
- return new Formula() {
+ private IntegrityFormula getInvalidFormula() {
+ return new AtomicFormula(0) {
@Override
- public boolean isSatisfied(AppInstallMetadata appInstallMetadata) {
- return false;
+ public int getTag() {
+ return 0;
}
@Override
- public int getTag() {
- return 0;
+ public boolean matches(AppInstallMetadata appInstallMetadata) {
+ return false;
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/integrity/utils/TestUtils.java b/services/tests/servicestests/src/com/android/server/integrity/utils/TestUtils.java
index e54410b04b79..55abc7c1050d 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/utils/TestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/utils/TestUtils.java
@@ -18,8 +18,8 @@ package com.android.server.integrity.utils;
public class TestUtils {
- public static String getBits(int component, int numOfBits) {
- return String.format("%" + numOfBits + "s", Integer.toBinaryString(component))
+ public static String getBits(long component, int numOfBits) {
+ return String.format("%" + numOfBits + "s", Long.toBinaryString(component))
.replace(' ', '0');
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 8329227360e7..cf51fa31fad3 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -20,6 +20,8 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_MORE_DETAILS;
+import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_UNSUSPEND;
import static android.content.res.Resources.ID_NULL;
import static org.hamcrest.CoreMatchers.is;
@@ -217,6 +219,7 @@ public class PackageManagerSettingsTests {
assertThat(params.dialogInfo.getTitleResId(), is(ID_NULL));
assertThat(params.dialogInfo.getIconResId(), is(TEST_RESOURCE_ID));
assertThat(params.dialogInfo.getNeutralButtonTextResId(), is(ID_NULL));
+ assertThat(params.dialogInfo.getNeutralButtonAction(), is(BUTTON_ACTION_MORE_DETAILS));
assertThat(params.dialogInfo.getDialogMessageResId(), is(ID_NULL));
}
@@ -243,12 +246,14 @@ public class PackageManagerSettingsTests {
.setTitle(0x11220002)
.setMessage("1st message")
.setNeutralButtonText(0x11220003)
+ .setNeutralButtonAction(BUTTON_ACTION_MORE_DETAILS)
.build();
final SuspendDialogInfo dialogInfo2 = new SuspendDialogInfo.Builder()
.setIcon(0x22220001)
.setTitle(0x22220002)
.setMessage("2nd message")
.setNeutralButtonText(0x22220003)
+ .setNeutralButtonAction(BUTTON_ACTION_UNSUSPEND)
.build();
ps1.addOrUpdateSuspension("suspendingPackage1", dialogInfo1, appExtras1, launcherExtras1,
diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java
index 7eccd6728533..322e448d983f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java
@@ -16,6 +16,9 @@
package com.android.server.pm;
+import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_MORE_DETAILS;
+import static android.content.pm.SuspendDialogInfo.BUTTON_ACTION_UNSUSPEND;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
@@ -39,7 +42,8 @@ public class SuspendDialogInfoTest {
.setIcon(VALID_TEST_RES_ID_1)
.setTitle(VALID_TEST_RES_ID_1)
.setMessage(VALID_TEST_RES_ID_1)
- .setNeutralButtonText(VALID_TEST_RES_ID_1);
+ .setNeutralButtonText(VALID_TEST_RES_ID_1)
+ .setNeutralButtonAction(BUTTON_ACTION_MORE_DETAILS);
}
@Test
@@ -73,6 +77,25 @@ public class SuspendDialogInfoTest {
}
@Test
+ public void equalsComparesButtonAction() {
+ final SuspendDialogInfo.Builder dialogBuilder1 = createDefaultDialogBuilder();
+ final SuspendDialogInfo.Builder dialogBuilder2 = createDefaultDialogBuilder();
+ assertEquals(dialogBuilder1.build(), dialogBuilder2.build());
+ // Only button action is different
+ dialogBuilder2.setNeutralButtonAction(BUTTON_ACTION_UNSUSPEND);
+ assertNotEquals(dialogBuilder1.build(), dialogBuilder2.build());
+ }
+
+ @Test
+ public void defaultButtonAction() {
+ final SuspendDialogInfo.Builder dialogBuilder = new SuspendDialogInfo.Builder()
+ .setIcon(VALID_TEST_RES_ID_1)
+ .setTitle(VALID_TEST_RES_ID_1)
+ .setMessage(VALID_TEST_RES_ID_1);
+ assertEquals(BUTTON_ACTION_MORE_DETAILS, dialogBuilder.build().getNeutralButtonAction());
+ }
+
+ @Test
public void equalsComparesMessageIds() {
final SuspendDialogInfo.Builder dialogBuilder1 = createDefaultDialogBuilder();
final SuspendDialogInfo.Builder dialogBuilder2 = createDefaultDialogBuilder();
diff --git a/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java b/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java
index f1b2ef811885..5d849c114e69 100644
--- a/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/IntervalStatsTests.java
@@ -92,6 +92,9 @@ public class IntervalStatsTests {
case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
event.mNotificationChannelId = "channel" + (i % 5); //"random" channel
break;
+ case UsageEvents.Event.LOCUS_ID_SET:
+ event.mLocusId = "locus" + (i % 7); //"random" locus
+ break;
}
intervalStats.addEvent(event);
diff --git a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
index e6bb244ef05b..f1c39067994c 100644
--- a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
+++ b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java
@@ -52,6 +52,7 @@ import java.util.Set;
public class UsageStatsDatabaseTest {
private static final int MAX_TESTED_VERSION = 5;
+ private static final int OLDER_VERSION_MAX_EVENT_TYPE = 29;
protected Context mContext;
private UsageStatsDatabase mUsageStatsDatabase;
private File mTestDir;
@@ -79,7 +80,7 @@ public class UsageStatsDatabaseTest {
mUsageStatsDatabase = new UsageStatsDatabase(mTestDir);
mUsageStatsDatabase.readMappingsLocked();
mUsageStatsDatabase.init(1);
- populateIntervalStats();
+ populateIntervalStats(MAX_TESTED_VERSION);
clearUsageStatsFiles();
}
@@ -117,7 +118,7 @@ public class UsageStatsDatabaseTest {
return sb.toString();
}
- private void populateIntervalStats() {
+ private void populateIntervalStats(int minVersion) {
final int numberOfEvents = 3000;
final int timeProgression = 23;
long time = System.currentTimeMillis() - (numberOfEvents*timeProgression);
@@ -147,9 +148,12 @@ public class UsageStatsDatabaseTest {
final int instanceId = i % 11;
event.mClass = ".fake.class.name" + instanceId;
event.mTimeStamp = time;
- event.mEventType = i % (MAX_EVENT_TYPE + 1); //"random" event type
event.mInstanceId = instanceId;
+ int maxEventType = (minVersion < 5) ? OLDER_VERSION_MAX_EVENT_TYPE : MAX_EVENT_TYPE;
+ event.mEventType = i % (maxEventType + 1); //"random" event type
+
+
final int rootPackageInt = (i % 5); // 5 "apps" start each task
event.mTaskRootPackage = "fake.package.name" + rootPackageInt;
@@ -174,6 +178,9 @@ public class UsageStatsDatabaseTest {
//"random" channel
event.mNotificationChannelId = "channel" + (i % 5);
break;
+ case Event.LOCUS_ID_SET:
+ event.mLocusId = "locus" + (i % 7); //"random" locus
+ break;
}
mIntervalStats.addEvent(event);
@@ -281,6 +288,10 @@ public class UsageStatsDatabaseTest {
assertEquals(e1.mNotificationChannelIdToken, e2.mNotificationChannelIdToken,
"Usage event " + debugId);
break;
+ case Event.LOCUS_ID_SET:
+ assertEquals(e1.mLocusIdToken, e2.mLocusIdToken,
+ "Usage event " + debugId);
+ break;
}
// fallthrough
case 4: // test fields added in version 4
@@ -392,6 +403,7 @@ public class UsageStatsDatabaseTest {
* version and read the automatically upgraded files on disk in the new file format.
*/
void runVersionChangeTest(int oldVersion, int newVersion, int interval) throws IOException {
+ populateIntervalStats(oldVersion);
// Write IntervalStats to disk in old version format
UsageStatsDatabase prevDB = new UsageStatsDatabase(mTestDir, oldVersion);
prevDB.readMappingsLocked();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 587cfbf062fb..651ad40a4781 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -98,6 +98,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
NotificationUsageStats mUsageStats;
@Mock
IAccessibilityManager mAccessibilityService;
+ NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
private NotificationManagerService mService;
private String mPkg = "com.android.server.notification";
@@ -148,7 +149,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
verify(mAccessibilityService).addClient(any(IAccessibilityManagerClient.class), anyInt());
assertTrue(accessibilityManager.isEnabled());
- mService = spy(new NotificationManagerService(getContext()));
+ mService = spy(new NotificationManagerService(getContext(), mNotificationRecordLogger));
mService.setAudioManager(mAudioManager);
mService.setVibrator(mVibrator);
mService.setSystemReady(true);
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 93e09dfb3f57..1b92abef7c94 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -256,6 +256,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
UserManager mUm;
@Mock
NotificationHistoryManager mHistoryManager;
+ NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
+
// Use a Testable subclass so we can simulate calls from the system without failing.
private static class TestableNotificationManagerService extends NotificationManagerService {
@@ -265,8 +267,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Nullable
NotificationAssistantAccessGrantedCallback mNotificationAssistantAccessGrantedCallback;
- TestableNotificationManagerService(Context context) {
- super(context);
+ TestableNotificationManagerService(Context context, NotificationRecordLogger logger) {
+ super(context, logger);
}
@Override
@@ -353,7 +355,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
- mService = new TestableNotificationManagerService(mContext);
+ mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger);
// Use this testable looper.
mTestableLooper = TestableLooper.get(this);
@@ -1118,6 +1120,61 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testEnqueueNotificationWithTag_WritesExpectedLog() throws Exception {
+ final String tag = "testEnqueueNotificationWithTag_WritesExpectedLog";
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
+ generateNotificationRecord(null).getNotification(), 0);
+ waitForIdle();
+ assertEquals(1, mNotificationRecordLogger.getCalls().size());
+ NotificationRecordLoggerFake.CallRecord call = mNotificationRecordLogger.get(0);
+ assertTrue(call.shouldLog());
+ assertNotNull(call.r);
+ assertNull(call.old);
+ assertEquals(0, call.position);
+ assertEquals(0, call.buzzBeepBlink);
+ assertEquals(PKG, call.r.sbn.getPackageName());
+ assertEquals(0, call.r.sbn.getId());
+ assertEquals(tag, call.r.sbn.getTag());
+ }
+
+ @Test
+ public void testEnqueueNotificationWithTag_LogsOnMajorUpdates() throws Exception {
+ final String tag = "testEnqueueNotificationWithTag_LogsOnMajorUpdates";
+ Notification original = new Notification.Builder(mContext,
+ mTestNotificationChannel.getId())
+ .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, original, 0);
+ Notification update = new Notification.Builder(mContext,
+ mTestNotificationChannel.getId())
+ .setSmallIcon(android.R.drawable.sym_def_app_icon)
+ .setCategory(Notification.CATEGORY_ALARM).build();
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0, update, 0);
+ waitForIdle();
+ assertEquals(2, mNotificationRecordLogger.getCalls().size());
+ assertTrue(mNotificationRecordLogger.get(0).shouldLog());
+ assertEquals(
+ NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_POSTED,
+ mNotificationRecordLogger.get(0).getUiEvent());
+ assertEquals(
+ NotificationRecordLogger.NotificationReportedEvents.NOTIFICATION_UPDATED,
+ mNotificationRecordLogger.get(1).getUiEvent());
+ assertTrue(mNotificationRecordLogger.get(1).shouldLog());
+ }
+
+ @Test
+ public void testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdates() throws Exception {
+ final String tag = "testEnqueueNotificationWithTag_DoesNotLogOnMinorUpdates";
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
+ generateNotificationRecord(null).getNotification(), 0);
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, tag, 0,
+ generateNotificationRecord(null).getNotification(), 0);
+ waitForIdle();
+ assertEquals(2, mNotificationRecordLogger.getCalls().size());
+ assertTrue(mNotificationRecordLogger.get(0).shouldLog());
+ assertFalse(mNotificationRecordLogger.get(1).shouldLog());
+ }
+
+ @Test
public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
mBinderService.enqueueNotificationWithTag(PKG, PKG,
"testCancelNotificationImmediatelyAfterEnqueue", 0,
@@ -2252,7 +2309,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testHasCompanionDevice_noService() {
- mService = new TestableNotificationManagerService(mContext);
+ mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger);
assertFalse(mService.hasCompanionDevice(mListener));
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java
new file mode 100644
index 000000000000..11972fd6a8dc
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordLoggerFake.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2020 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.notification;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Fake implementation of NotificationRecordLogger, for testing.
+ */
+class NotificationRecordLoggerFake implements NotificationRecordLogger {
+ class CallRecord extends NotificationRecordPair {
+ public int position, buzzBeepBlink;
+ CallRecord(NotificationRecord r, NotificationRecord old, int position,
+ int buzzBeepBlink) {
+ super(r, old);
+ this.position = position;
+ this.buzzBeepBlink = buzzBeepBlink;
+ }
+ boolean shouldLog() {
+ return shouldLog(buzzBeepBlink);
+ }
+ }
+ List<CallRecord> mCalls = new ArrayList<CallRecord>();
+
+ List<CallRecord> getCalls() {
+ return mCalls;
+ }
+
+ CallRecord get(int index) {
+ return mCalls.get(index);
+ }
+
+ @Override
+ public void logNotificationReported(NotificationRecord r, NotificationRecord old,
+ int position, int buzzBeepBlink) {
+ mCalls.add(new CallRecord(r, old, position, buzzBeepBlink));
+ }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
index c828f02901b3..e18c8919b645 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java
@@ -18,7 +18,6 @@ package com.android.server.notification;
import static android.app.role.RoleManager.ROLE_DIALER;
import static android.app.role.RoleManager.ROLE_EMERGENCY;
-import static android.app.role.RoleManager.ROLE_SMS;
import static android.content.pm.PackageManager.MATCH_ALL;
import static junit.framework.Assert.assertFalse;
@@ -92,24 +91,20 @@ public class RoleObserverTest extends UiServiceTestCase {
private Executor mExecutor;
@Mock
private RoleManager mRoleManager;
+ NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
private List<UserInfo> mUsers;
private static class TestableNotificationManagerService extends NotificationManagerService {
-
- TestableNotificationManagerService(Context context) {
- super(context);
+ TestableNotificationManagerService(Context context, NotificationRecordLogger logger) {
+ super(context, logger);
}
@Override
- protected void handleSavePolicyFile() {
- return;
- }
+ protected void handleSavePolicyFile() { }
@Override
- protected void loadPolicyFile() {
- return;
- }
+ protected void loadPolicyFile() { }
}
@Before
@@ -125,7 +120,7 @@ public class RoleObserverTest extends UiServiceTestCase {
mUsers.add(new UserInfo(10, "second", 0));
when(mUm.getUsers()).thenReturn(mUsers);
- mService = new TestableNotificationManagerService(mContext);
+ mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger);
mRoleObserver = mService.new RoleObserver(mRoleManager, mPm, mExecutor);
try {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index 135d00586329..399cf49ac06f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
@@ -45,7 +44,6 @@ import android.testing.DexmakerShareClassLoaderRule;
import androidx.test.filters.SmallTest;
-import com.android.internal.app.BlockedAppActivity;
import com.android.internal.app.HarmfulAppWarningActivity;
import com.android.internal.app.SuspendedAppActivity;
import com.android.internal.app.UnlaunchableAppActivity;
@@ -107,8 +105,6 @@ public class ActivityStartInterceptorTest {
private PackageManagerService mPackageManager;
@Mock
private ActivityManagerInternal mAmInternal;
- @Mock
- private LockTaskController mLockTaskController;
private ActivityStartInterceptor mInterceptor;
private ActivityInfo mAInfo = new ActivityInfo();
@@ -149,13 +145,6 @@ public class ActivityStartInterceptorTest {
when(mPackageManager.getHarmfulAppWarning(TEST_PACKAGE_NAME, TEST_USER_ID))
.thenReturn(null);
- // Mock LockTaskController
- mAInfo.lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
- when(mService.getLockTaskController()).thenReturn(mLockTaskController);
- when(mLockTaskController.isActivityAllowed(
- TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT))
- .thenReturn(true);
-
// Initialise activity info
mAInfo.applicationInfo = new ApplicationInfo();
mAInfo.packageName = mAInfo.applicationInfo.packageName = TEST_PACKAGE_NAME;
@@ -207,18 +196,6 @@ public class ActivityStartInterceptorTest {
}
@Test
- public void testInterceptLockTaskModeViolationPackage() {
- when(mLockTaskController.isActivityAllowed(
- TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT))
- .thenReturn(false);
-
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null));
-
- assertTrue(BlockedAppActivity.createIntent(TEST_USER_ID, TEST_PACKAGE_NAME)
- .filterEquals(mInterceptor.mIntent));
- }
-
- @Test
public void testInterceptQuietProfile() {
// GIVEN that the user the activity is starting as is currently in quiet mode
when(mUserManager.isQuietModeEnabled(eq(UserHandle.of(TEST_USER_ID)))).thenReturn(true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
index 75ec53d69a71..039ff604f3f1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
@@ -29,9 +29,6 @@ import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.os.Process.SYSTEM_UID;
import static android.telecom.TelecomManager.EMERGENCY_DIALER_COMPONENT;
@@ -696,38 +693,6 @@ public class LockTaskControllerTest {
assertTrue((StatusBarManager.DISABLE2_QUICK_SETTINGS & flags.second) != 0);
}
- @Test
- public void testIsActivityAllowed() {
- // WHEN lock task mode is not enabled
- assertTrue(mLockTaskController.isActivityAllowed(
- TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT));
-
- // WHEN lock task mode is enabled
- Task tr = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
- mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
-
-
- // package with LOCK_TASK_LAUNCH_MODE_ALWAYS should always be allowed
- assertTrue(mLockTaskController.isActivityAllowed(
- TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_ALWAYS));
-
- // unwhitelisted package should not be allowed
- assertFalse(mLockTaskController.isActivityAllowed(
- TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT));
-
- // update the whitelist
- String[] whitelist = new String[] { TEST_PACKAGE_NAME };
- mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist);
-
- // whitelisted package should be allowed
- assertTrue(mLockTaskController.isActivityAllowed(
- TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT));
-
- // package with LOCK_TASK_LAUNCH_MODE_NEVER should never be allowed
- assertFalse(mLockTaskController.isActivityAllowed(
- TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_NEVER));
- }
-
private Task getTask(int lockTaskAuth) {
return getTask(TEST_PACKAGE_NAME, lockTaskAuth);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index eb8eb98fd484..d73830468359 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -31,6 +31,7 @@ import android.graphics.Rect;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.util.ArraySet;
+import android.view.Surface;
import android.view.View;
import androidx.test.filters.MediumTest;
@@ -47,7 +48,7 @@ import java.util.function.Predicate;
* Test class for {@link TaskSnapshotPersister} and {@link TaskSnapshotLoader}
*
* Build/Install/Run:
- * atest WmTests:TaskSnapshotPersisterLoaderTest
+ * atest TaskSnapshotPersisterLoaderTest
*/
@MediumTest
@Presubmit
@@ -316,4 +317,18 @@ public class TaskSnapshotPersisterLoaderTest extends TaskSnapshotPersisterTestBa
new File(FILES_DIR.getPath() + "/snapshots/2_reduced.jpg")};
assertTrueForFiles(existsFiles, File::exists, " must exist");
}
+
+ @Test
+ public void testRotationPersistAndLoadSnapshot() {
+ TaskSnapshot a = new TaskSnapshotBuilder()
+ .setRotation(Surface.ROTATION_270)
+ .build();
+ mPersister.persistSnapshot(1 , mTestUserId, createSnapshot());
+ mPersister.persistSnapshot(2 , mTestUserId, a);
+ mPersister.waitForQueueEmpty();
+ final TaskSnapshot snapshotA = mLoader.loadTask(1, mTestUserId, false /* reduced */);
+ final TaskSnapshot snapshotB = mLoader.loadTask(2, mTestUserId, false /* reduced */);
+ assertEquals(Surface.ROTATION_0, snapshotA.getRotation());
+ assertEquals(Surface.ROTATION_270, snapshotB.getRotation());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index f7496229f66b..f86c9e63dc48 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -32,6 +32,7 @@ import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.UserManager;
+import android.view.Surface;
import org.junit.After;
import org.junit.Before;
@@ -93,6 +94,7 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase {
private boolean mIsTranslucent = false;
private int mWindowingMode = WINDOWING_MODE_FULLSCREEN;
private int mSystemUiVisibility = 0;
+ private int mRotation = Surface.ROTATION_0;
TaskSnapshotBuilder setScale(float scale) {
mScale = scale;
@@ -124,6 +126,11 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase {
return this;
}
+ TaskSnapshotBuilder setRotation(int rotation) {
+ mRotation = rotation;
+ return this;
+ }
+
TaskSnapshot build() {
final GraphicBuffer buffer = GraphicBuffer.create(100, 100, PixelFormat.RGBA_8888,
USAGE_HW_TEXTURE | USAGE_SW_READ_RARELY | USAGE_SW_READ_RARELY);
@@ -131,7 +138,8 @@ class TaskSnapshotPersisterTestBase extends WindowTestsBase {
c.drawColor(Color.RED);
buffer.unlockCanvasAndPost(c);
return new TaskSnapshot(MOCK_SNAPSHOT_ID, new ComponentName("", ""), buffer,
- ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, TEST_INSETS,
+ ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
+ mRotation, TEST_INSETS,
mReducedResolution, mScale, mIsRealSnapshot,
mWindowingMode, mSystemUiVisibility, mIsTranslucent);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index ed87f3a0c604..bb0e5aec8e2e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -40,6 +40,7 @@ import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
+import android.view.Surface;
import android.view.SurfaceControl;
import androidx.test.filters.SmallTest;
@@ -69,7 +70,8 @@ public class TaskSnapshotSurfaceTest extends WindowTestsBase {
final TaskSnapshot snapshot = new TaskSnapshot(
System.currentTimeMillis(),
new ComponentName("", ""), buffer,
- ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT, contentInsets, false,
+ ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
+ Surface.ROTATION_0, contentInsets, false,
1.0f, true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN,
0 /* systemUiVisibility */, false /* isTranslucent */);
mSurface = new TaskSnapshotSurface(mWm, new Window(), new SurfaceControl(), snapshot, "Test",
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index 8fb283adc740..8fadf5eb9333 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -28,6 +28,7 @@ import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP;
import static android.app.usage.UsageEvents.Event.KEYGUARD_HIDDEN;
import static android.app.usage.UsageEvents.Event.KEYGUARD_SHOWN;
+import static android.app.usage.UsageEvents.Event.LOCUS_ID_SET;
import static android.app.usage.UsageEvents.Event.NOTIFICATION_INTERRUPTION;
import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;
import static android.app.usage.UsageEvents.Event.SCREEN_INTERACTIVE;
@@ -568,6 +569,16 @@ public class IntervalStats {
continue;
}
break;
+ case LOCUS_ID_SET:
+ event.mLocusId = packagesTokenData.getString(packageToken, event.mLocusIdToken);
+ if (event.mLocusId == null) {
+ Slog.e(TAG, "Unable to parse locus " + event.mLocusIdToken
+ + " for package " + packageToken);
+ this.events.remove(i);
+ dataOmitted = true;
+ continue;
+ }
+ break;
}
}
return dataOmitted;
@@ -675,6 +686,12 @@ public class IntervalStats {
packageToken, event.mPackage, event.mNotificationChannelId);
}
break;
+ case LOCUS_ID_SET:
+ if (!TextUtils.isEmpty(event.mLocusId)) {
+ event.mLocusIdToken = packagesTokenData.getTokenOrAdd(packageToken,
+ event.mPackage, event.mLocusId);
+ }
+ break;
}
}
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java b/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
index fe5da923597e..e4aa9fe0dc1e 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
@@ -277,6 +277,10 @@ final class UsageStatsProtoV2 {
event.mTaskRootClassToken = proto.readInt(
EventObfuscatedProto.TASK_ROOT_CLASS_TOKEN) - 1;
break;
+ case (int) EventObfuscatedProto.LOCUS_ID_TOKEN:
+ event.mLocusIdToken = proto.readInt(
+ EventObfuscatedProto.LOCUS_ID_TOKEN) - 1;
+ break;
case ProtoInputStream.NO_MORE_FIELDS:
// timeStamp was not read, assume default value 0 plus beginTime
if (event.mTimeStamp == 0) {
@@ -398,6 +402,11 @@ final class UsageStatsProtoV2 {
proto.write(EventObfuscatedProto.SHORTCUT_ID_TOKEN, event.mShortcutIdToken + 1);
}
break;
+ case UsageEvents.Event.LOCUS_ID_SET:
+ if (event.mLocusIdToken != PackagesTokenData.UNASSIGNED_TOKEN) {
+ proto.write(EventObfuscatedProto.LOCUS_ID_TOKEN, event.mLocusIdToken + 1);
+ }
+ break;
case UsageEvents.Event.NOTIFICATION_INTERRUPTION:
if (event.mNotificationChannelIdToken != PackagesTokenData.UNASSIGNED_TOKEN) {
proto.write(EventObfuscatedProto.NOTIFICATION_CHANNEL_ID_TOKEN,
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 5119e5824f7f..9a18f8cd3a46 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -21,6 +21,7 @@ import static android.app.usage.UsageEvents.Event.CONFIGURATION_CHANGE;
import static android.app.usage.UsageEvents.Event.DEVICE_EVENT_PACKAGE_NAME;
import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN;
import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK;
+import static android.app.usage.UsageEvents.Event.LOCUS_ID_SET;
import static android.app.usage.UsageEvents.Event.NOTIFICATION_INTERRUPTION;
import static android.app.usage.UsageEvents.Event.SHORTCUT_INVOCATION;
import static android.app.usage.UsageEvents.Event.USER_STOPPED;
@@ -30,6 +31,8 @@ import static android.app.usage.UsageStatsManager.USAGE_SOURCE_TASK_ROOT_ACTIVIT
import android.Manifest;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.IUidObserver;
@@ -52,6 +55,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.LocusId;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
@@ -1987,6 +1991,17 @@ public class UsageStatsService extends SystemService implements
}
@Override
+ public void reportLocusUpdate(@NonNull ComponentName activity, @UserIdInt int userId,
+ @Nullable LocusId locusId, @NonNull IBinder appToken) {
+ Event event = new Event(LOCUS_ID_SET, SystemClock.elapsedRealtime());
+ event.mLocusId = locusId.getId();
+ event.mPackage = activity.getPackageName();
+ event.mClass = activity.getClassName();
+ event.mInstanceId = appToken.hashCode();
+ reportEventOrAddToQueue(userId, event);
+ }
+
+ @Override
public void reportContentProviderUsage(String name, String packageName, int userId) {
mAppStandby.postReportContentProviderUsage(name, packageName, userId);
}
diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
index 56c342ee72ca..553bcff931d2 100644
--- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
@@ -20,12 +20,10 @@ import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.res.Resources;
-import android.os.RemoteException;
import android.os.UserHandle;
-import android.permission.IPermissionManager;
+import android.permission.PermissionManager;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
@@ -76,7 +74,6 @@ public final class CarrierAppUtils {
* privileged apps may have changed.
*/
public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage,
- IPackageManager packageManager, IPermissionManager permissionManager,
TelephonyManager telephonyManager, int userId, Context context) {
if (DEBUG) {
Log.d(TAG, "disableCarrierAppsUntilPrivileged");
@@ -87,14 +84,14 @@ public final class CarrierAppUtils {
ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed =
config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
ContentResolver contentResolver = getContentResolverForUser(context, userId);
- disableCarrierAppsUntilPrivileged(callingPackage, packageManager, permissionManager,
- telephonyManager, contentResolver, userId, systemCarrierAppsDisabledUntilUsed,
- systemCarrierAssociatedAppsDisabledUntilUsed);
+ disableCarrierAppsUntilPrivileged(callingPackage, telephonyManager, contentResolver,
+ userId, systemCarrierAppsDisabledUntilUsed,
+ systemCarrierAssociatedAppsDisabledUntilUsed, context);
}
/**
- * Like {@link #disableCarrierAppsUntilPrivileged(String, IPackageManager, TelephonyManager,
- * ContentResolver, int)}, but assumes that no carrier apps have carrier privileges.
+ * Like {@link #disableCarrierAppsUntilPrivileged(String, TelephonyManager, int, Context)},
+ * but assumes that no carrier apps have carrier privileges.
*
* This prevents a potential race condition on first boot - since the app's default state is
* enabled, we will initially disable it when the telephony stack is first initialized as it has
@@ -104,8 +101,7 @@ public final class CarrierAppUtils {
* Manager can kill it, and this can lead to crashes as the app is in an unexpected state.
*/
public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage,
- IPackageManager packageManager, IPermissionManager permissionManager, int userId,
- Context context) {
+ int userId, Context context) {
if (DEBUG) {
Log.d(TAG, "disableCarrierAppsUntilPrivileged");
}
@@ -113,13 +109,12 @@ public final class CarrierAppUtils {
ArraySet<String> systemCarrierAppsDisabledUntilUsed =
config.getDisabledUntilUsedPreinstalledCarrierApps();
-
ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed =
config.getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
ContentResolver contentResolver = getContentResolverForUser(context, userId);
- disableCarrierAppsUntilPrivileged(callingPackage, packageManager, permissionManager,
- null /* telephonyManager */, contentResolver, userId,
- systemCarrierAppsDisabledUntilUsed, systemCarrierAssociatedAppsDisabledUntilUsed);
+ disableCarrierAppsUntilPrivileged(callingPackage, null /* telephonyManager */,
+ contentResolver, userId, systemCarrierAppsDisabledUntilUsed,
+ systemCarrierAssociatedAppsDisabledUntilUsed, context);
}
private static ContentResolver getContentResolverForUser(Context context, int userId) {
@@ -135,21 +130,21 @@ public final class CarrierAppUtils {
// Must be public b/c framework unit tests can't access package-private methods.
@VisibleForTesting
public static void disableCarrierAppsUntilPrivileged(String callingPackage,
- IPackageManager packageManager, IPermissionManager permissionManager,
- @Nullable TelephonyManager telephonyManager,
- ContentResolver contentResolver, int userId,
- ArraySet<String> systemCarrierAppsDisabledUntilUsed,
- ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed) {
+ @Nullable TelephonyManager telephonyManager, ContentResolver contentResolver,
+ int userId, ArraySet<String> systemCarrierAppsDisabledUntilUsed,
+ ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed,
+ Context context) {
+ PackageManager packageManager = context.getPackageManager();
+ PermissionManager permissionManager =
+ (PermissionManager) context.getSystemService(Context.PERMISSION_SERVICE);
List<ApplicationInfo> candidates = getDefaultNotUpdatedCarrierAppCandidatesHelper(
- packageManager, userId, systemCarrierAppsDisabledUntilUsed);
+ userId, systemCarrierAppsDisabledUntilUsed, context);
if (candidates == null || candidates.isEmpty()) {
return;
}
Map<String, List<ApplicationInfo>> associatedApps = getDefaultCarrierAssociatedAppsHelper(
- packageManager,
- userId,
- systemCarrierAssociatedAppsDisabledUntilUsed);
+ userId, systemCarrierAssociatedAppsDisabledUntilUsed, context);
List<String> enabledCarrierPackages = new ArrayList<>();
boolean hasRunOnce = Settings.Secure.getInt(contentResolver,
@@ -166,19 +161,18 @@ public final class CarrierAppUtils {
&& !ArrayUtils.contains(restrictedCarrierApps, packageName);
// add hiddenUntilInstalled flag for carrier apps and associated apps
- packageManager.setSystemAppHiddenUntilInstalled(packageName, true);
+ packageManager.setSystemAppState(
+ packageName, PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
List<ApplicationInfo> associatedAppList = associatedApps.get(packageName);
if (associatedAppList != null) {
for (ApplicationInfo associatedApp : associatedAppList) {
- packageManager.setSystemAppHiddenUntilInstalled(
- associatedApp.packageName,
- true
- );
+ packageManager.setSystemAppState(associatedApp.packageName,
+ PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
}
}
- int enabledSetting = packageManager.getApplicationEnabledSetting(packageName,
- userId);
+ int enabledSetting = context.createContextAsUser(UserHandle.of(userId), 0)
+ .getPackageManager().getApplicationEnabledSetting(packageName);
if (hasPrivileges) {
// Only update enabled state for the app on /system. Once it has been
// updated we shouldn't touch it.
@@ -189,24 +183,25 @@ public final class CarrierAppUtils {
|| (ai.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
Log.i(TAG, "Update state(" + packageName + "): ENABLED for user "
+ userId);
- packageManager.setSystemAppInstallState(
- packageName,
- true /*installed*/,
- userId);
- packageManager.setApplicationEnabledSetting(
- packageName,
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
- PackageManager.DONT_KILL_APP,
- userId,
- callingPackage);
+ context.createContextAsUser(UserHandle.of(userId), 0)
+ .getPackageManager()
+ .setSystemAppState(
+ packageName, PackageManager.SYSTEM_APP_STATE_INSTALLED);
+ context.createPackageContextAsUser(callingPackage, 0, UserHandle.of(userId))
+ .getPackageManager()
+ .setApplicationEnabledSetting(
+ packageName,
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP);
}
// Also enable any associated apps for this carrier app.
if (associatedAppList != null) {
for (ApplicationInfo associatedApp : associatedAppList) {
- int associatedAppEnabledSetting =
- packageManager.getApplicationEnabledSetting(
- associatedApp.packageName, userId);
+ int associatedAppEnabledSetting = context
+ .createContextAsUser(UserHandle.of(userId), 0)
+ .getPackageManager()
+ .getApplicationEnabledSetting(associatedApp.packageName);
if (associatedAppEnabledSetting
== PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
|| associatedAppEnabledSetting
@@ -215,16 +210,17 @@ public final class CarrierAppUtils {
& ApplicationInfo.FLAG_INSTALLED) == 0) {
Log.i(TAG, "Update associated state(" + associatedApp.packageName
+ "): ENABLED for user " + userId);
- packageManager.setSystemAppInstallState(
- associatedApp.packageName,
- true /*installed*/,
- userId);
- packageManager.setApplicationEnabledSetting(
- associatedApp.packageName,
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
- PackageManager.DONT_KILL_APP,
- userId,
- callingPackage);
+ context.createContextAsUser(UserHandle.of(userId), 0)
+ .getPackageManager()
+ .setSystemAppState(associatedApp.packageName,
+ PackageManager.SYSTEM_APP_STATE_INSTALLED);
+ context.createPackageContextAsUser(
+ callingPackage, 0, UserHandle.of(userId))
+ .getPackageManager()
+ .setApplicationEnabledSetting(
+ associatedApp.packageName,
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP);
}
}
}
@@ -239,10 +235,10 @@ public final class CarrierAppUtils {
&& (ai.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
Log.i(TAG, "Update state(" + packageName
+ "): DISABLED_UNTIL_USED for user " + userId);
- packageManager.setSystemAppInstallState(
- packageName,
- false /*installed*/,
- userId);
+ context.createContextAsUser(UserHandle.of(userId), 0)
+ .getPackageManager()
+ .setSystemAppState(
+ packageName, PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
}
// Also disable any associated apps for this carrier app if this is the first
@@ -251,9 +247,10 @@ public final class CarrierAppUtils {
if (!hasRunOnce) {
if (associatedAppList != null) {
for (ApplicationInfo associatedApp : associatedAppList) {
- int associatedAppEnabledSetting =
- packageManager.getApplicationEnabledSetting(
- associatedApp.packageName, userId);
+ int associatedAppEnabledSetting = context
+ .createContextAsUser(UserHandle.of(userId), 0)
+ .getPackageManager()
+ .getApplicationEnabledSetting(associatedApp.packageName);
if (associatedAppEnabledSetting
== PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
&& (associatedApp.flags
@@ -261,10 +258,10 @@ public final class CarrierAppUtils {
Log.i(TAG,
"Update associated state(" + associatedApp.packageName
+ "): DISABLED_UNTIL_USED for user " + userId);
- packageManager.setSystemAppInstallState(
- associatedApp.packageName,
- false /*installed*/,
- userId);
+ context.createContextAsUser(UserHandle.of(userId), 0)
+ .getPackageManager()
+ .setSystemAppState(associatedApp.packageName,
+ PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
}
}
}
@@ -282,9 +279,10 @@ public final class CarrierAppUtils {
// apps.
String[] packageNames = new String[enabledCarrierPackages.size()];
enabledCarrierPackages.toArray(packageNames);
- permissionManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId);
+ permissionManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames,
+ UserHandle.of(userId), Runnable::run, isSuccess -> { });
}
- } catch (RemoteException e) {
+ } catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Could not reach PackageManager", e);
}
}
@@ -293,13 +291,13 @@ public final class CarrierAppUtils {
* Returns the list of "default" carrier apps.
*
* This is the subset of apps returned by
- * {@link #getDefaultCarrierAppCandidates(IPackageManager, int)} which currently have carrier
+ * {@link #getDefaultCarrierAppCandidates(int, Context)} which currently have carrier
* privileges per the SIM(s) inserted in the device.
*/
- public static List<ApplicationInfo> getDefaultCarrierApps(IPackageManager packageManager,
- TelephonyManager telephonyManager, int userId) {
+ public static List<ApplicationInfo> getDefaultCarrierApps(
+ TelephonyManager telephonyManager, int userId, Context context) {
// Get all system apps from the default list.
- List<ApplicationInfo> candidates = getDefaultCarrierAppCandidates(packageManager, userId);
+ List<ApplicationInfo> candidates = getDefaultCarrierAppCandidates(userId, context);
if (candidates == null || candidates.isEmpty()) {
return null;
}
@@ -325,25 +323,23 @@ public final class CarrierAppUtils {
* Returns the list of "default" carrier app candidates.
*
* These are the apps subject to the hiding/showing logic in
- * {@link CarrierAppUtils#disableCarrierAppsUntilPrivileged(String, IPackageManager,
- * TelephonyManager, ContentResolver, int)}, as well as the apps which should have default
+ * {@link CarrierAppUtils#disableCarrierAppsUntilPrivileged(String, TelephonyManager, int,
+ * Context)}, as well as the apps which should have default
* permissions granted, when a matching SIM is inserted.
*
* Whether or not the app is actually considered a default app depends on whether the app has
* carrier privileges as determined by the SIMs in the device.
*/
public static List<ApplicationInfo> getDefaultCarrierAppCandidates(
- IPackageManager packageManager, int userId) {
+ int userId, Context context) {
ArraySet<String> systemCarrierAppsDisabledUntilUsed =
SystemConfig.getInstance().getDisabledUntilUsedPreinstalledCarrierApps();
- return getDefaultCarrierAppCandidatesHelper(packageManager, userId,
- systemCarrierAppsDisabledUntilUsed);
+ return getDefaultCarrierAppCandidatesHelper(userId, systemCarrierAppsDisabledUntilUsed,
+ context);
}
private static List<ApplicationInfo> getDefaultCarrierAppCandidatesHelper(
- IPackageManager packageManager,
- int userId,
- ArraySet<String> systemCarrierAppsDisabledUntilUsed) {
+ int userId, ArraySet<String> systemCarrierAppsDisabledUntilUsed, Context context) {
if (systemCarrierAppsDisabledUntilUsed == null) {
return null;
}
@@ -357,7 +353,7 @@ public final class CarrierAppUtils {
for (int i = 0; i < size; i++) {
String packageName = systemCarrierAppsDisabledUntilUsed.valueAt(i);
ApplicationInfo ai =
- getApplicationInfoIfSystemApp(packageManager, userId, packageName);
+ getApplicationInfoIfSystemApp(userId, packageName, context);
if (ai != null) {
apps.add(ai);
}
@@ -366,9 +362,7 @@ public final class CarrierAppUtils {
}
private static List<ApplicationInfo> getDefaultNotUpdatedCarrierAppCandidatesHelper(
- IPackageManager packageManager,
- int userId,
- ArraySet<String> systemCarrierAppsDisabledUntilUsed) {
+ int userId, ArraySet<String> systemCarrierAppsDisabledUntilUsed, Context context) {
if (systemCarrierAppsDisabledUntilUsed == null) {
return null;
}
@@ -382,7 +376,7 @@ public final class CarrierAppUtils {
for (int i = 0; i < size; i++) {
String packageName = systemCarrierAppsDisabledUntilUsed.valueAt(i);
ApplicationInfo ai =
- getApplicationInfoIfNotUpdatedSystemApp(packageManager, userId, packageName);
+ getApplicationInfoIfNotUpdatedSystemApp(userId, packageName, context);
if (ai != null) {
apps.add(ai);
}
@@ -391,9 +385,8 @@ public final class CarrierAppUtils {
}
private static Map<String, List<ApplicationInfo>> getDefaultCarrierAssociatedAppsHelper(
- IPackageManager packageManager,
- int userId,
- ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed) {
+ int userId, ArrayMap<String, List<String>> systemCarrierAssociatedAppsDisabledUntilUsed,
+ Context context) {
int size = systemCarrierAssociatedAppsDisabledUntilUsed.size();
Map<String, List<ApplicationInfo>> associatedApps = new ArrayMap<>(size);
for (int i = 0; i < size; i++) {
@@ -403,7 +396,7 @@ public final class CarrierAppUtils {
for (int j = 0; j < associatedAppPackages.size(); j++) {
ApplicationInfo ai =
getApplicationInfoIfNotUpdatedSystemApp(
- packageManager, userId, associatedAppPackages.get(j));
+ userId, associatedAppPackages.get(j), context);
// Only update enabled state for the app on /system. Once it has been updated we
// shouldn't touch it.
if (ai != null) {
@@ -421,19 +414,19 @@ public final class CarrierAppUtils {
@Nullable
private static ApplicationInfo getApplicationInfoIfNotUpdatedSystemApp(
- IPackageManager packageManager,
- int userId,
- String packageName) {
+ int userId, String packageName, Context context) {
try {
- ApplicationInfo ai = packageManager.getApplicationInfo(packageName,
- PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
- | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
- | PackageManager.MATCH_SYSTEM_ONLY
- | PackageManager.MATCH_FACTORY_ONLY, userId);
+ ApplicationInfo ai = context.createContextAsUser(UserHandle.of(userId), 0)
+ .getPackageManager()
+ .getApplicationInfo(packageName,
+ PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
+ | PackageManager.MATCH_SYSTEM_ONLY
+ | PackageManager.MATCH_FACTORY_ONLY);
if (ai != null) {
return ai;
}
- } catch (RemoteException e) {
+ } catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Could not reach PackageManager", e);
}
return null;
@@ -441,18 +434,18 @@ public final class CarrierAppUtils {
@Nullable
private static ApplicationInfo getApplicationInfoIfSystemApp(
- IPackageManager packageManager,
- int userId,
- String packageName) {
+ int userId, String packageName, Context context) {
try {
- ApplicationInfo ai = packageManager.getApplicationInfo(packageName,
- PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
- | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
- | PackageManager.MATCH_SYSTEM_ONLY, userId);
+ ApplicationInfo ai = context.createContextAsUser(UserHandle.of(userId), 0)
+ .getPackageManager()
+ .getApplicationInfo(packageName,
+ PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
+ | PackageManager.MATCH_SYSTEM_ONLY);
if (ai != null) {
return ai;
}
- } catch (RemoteException e) {
+ } catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Could not reach PackageManager", e);
}
return null;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 1d89665c1670..86913a636913 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -7348,6 +7348,30 @@ public class TelephonyManager {
}
}
+
+ /**
+ * Resets the {@link android.telephony.ims.ImsService} associated with the specified sim slot.
+ * Used by diagnostic apps to force the IMS stack to be disabled and re-enabled in an effort to
+ * recover from scenarios where the {@link android.telephony.ims.ImsService} gets in to a bad
+ * state.
+ *
+ * @param slotIndex the sim slot to reset the IMS stack on.
+ * @hide */
+ @SystemApi
+ @WorkerThread
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public void resetIms(int slotIndex) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ telephony.resetIms(slotIndex);
+ }
+ } catch (RemoteException e) {
+ Rlog.e(TAG, "toggleImsOnOff, RemoteException: "
+ + e.getMessage());
+ }
+ }
+
/**
* Enables IMS for the framework. This will trigger IMS registration and ImsFeature capability
* status updates, if not already enabled.
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 6aa5a52d55d5..3f573c92d022 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -831,6 +831,11 @@ interface ITelephony {
void disableIms(int slotId);
/**
+ * Toggle framework IMS disables and enables.
+ */
+ void resetIms(int slotIndex);
+
+ /**
* Get IImsMmTelFeature binder from ImsResolver that corresponds to the subId and MMTel feature
* as well as registering the MmTelFeature for callbacks using the IImsServiceFeatureCallback
* interface.
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index 797fd83321f7..3e4f3d818840 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -269,6 +269,7 @@ public class NetworkCapabilitiesTest {
.setUids(uids)
.addCapability(NET_CAPABILITY_EIMS)
.addCapability(NET_CAPABILITY_NOT_METERED);
+ netCap.setOwnerUid(123);
assertParcelingIsLossless(netCap);
netCap.setSSID(TEST_SSID);
assertParcelSane(netCap, 13);
diff --git a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java b/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
index 065add4fc253..7ab4b56fae80 100644
--- a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
+++ b/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
@@ -16,6 +16,8 @@
package android.net;
+import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsBinder;
+import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
import static android.net.ConnectivityDiagnosticsManager.DataStallReport;
@@ -25,12 +27,19 @@ 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 static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import android.os.PersistableBundle;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+
+import java.util.concurrent.Executor;
@RunWith(JUnit4.class)
public class ConnectivityDiagnosticsManagerTest {
@@ -41,6 +50,19 @@ public class ConnectivityDiagnosticsManagerTest {
private static final String BUNDLE_KEY = "key";
private static final String BUNDLE_VALUE = "value";
+ private static final Executor INLINE_EXECUTOR = x -> x.run();
+
+ @Mock private ConnectivityDiagnosticsCallback mCb;
+
+ private ConnectivityDiagnosticsBinder mBinder;
+
+ @Before
+ public void setUp() {
+ mCb = mock(ConnectivityDiagnosticsCallback.class);
+
+ mBinder = new ConnectivityDiagnosticsBinder(mCb, INLINE_EXECUTOR);
+ }
+
private ConnectivityReport createSampleConnectivityReport() {
final LinkProperties linkProperties = new LinkProperties();
linkProperties.setInterfaceName(INTERFACE_NAME);
@@ -193,4 +215,34 @@ public class ConnectivityDiagnosticsManagerTest {
public void testDataStallReportParcelUnparcel() {
assertParcelSane(createSampleDataStallReport(), 4);
}
+
+ @Test
+ public void testConnectivityDiagnosticsCallbackOnConnectivityReport() {
+ mBinder.onConnectivityReport(createSampleConnectivityReport());
+
+ // The callback will be invoked synchronously by inline executor. Immediately check the
+ // latch without waiting.
+ verify(mCb).onConnectivityReport(eq(createSampleConnectivityReport()));
+ }
+
+ @Test
+ public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() {
+ mBinder.onDataStallSuspected(createSampleDataStallReport());
+
+ // The callback will be invoked synchronously by inline executor. Immediately check the
+ // latch without waiting.
+ verify(mCb).onDataStallSuspected(eq(createSampleDataStallReport()));
+ }
+
+ @Test
+ public void testConnectivityDiagnosticsCallbackOnNetworkConnectivityReported() {
+ final Network n = new Network(NET_ID);
+ final boolean connectivity = true;
+
+ mBinder.onNetworkConnectivityReported(n, connectivity);
+
+ // The callback will be invoked synchronously by inline executor. Immediately check the
+ // latch without waiting.
+ verify(mCb).onNetworkConnectivityReported(eq(n), eq(connectivity));
+ }
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 09cc69e83f41..a0a1352a6330 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -6313,12 +6313,24 @@ public class ConnectivityServiceTest {
assertEquals(wifiLp, mService.getActiveLinkProperties());
}
+ @Test
+ public void testNetworkCapabilitiesRestrictedForCallerPermissions() {
+ int callerUid = Process.myUid();
+ final NetworkCapabilities originalNc = new NetworkCapabilities();
+ originalNc.setOwnerUid(callerUid);
+
+ final NetworkCapabilities newNc =
+ mService.networkCapabilitiesRestrictedForCallerPermissions(
+ originalNc, Process.myPid(), callerUid);
+
+ assertEquals(Process.INVALID_UID, newNc.getOwnerUid());
+ }
- private TestNetworkAgentWrapper establishVpn(LinkProperties lp, int establishingUid,
- Set<UidRange> vpnRange) throws Exception {
+ private TestNetworkAgentWrapper establishVpn(
+ LinkProperties lp, int ownerUid, Set<UidRange> vpnRange) throws Exception {
final TestNetworkAgentWrapper
vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp);
- vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
+ vpnNetworkAgent.getNetworkCapabilities().setOwnerUid(ownerUid);
mMockVpn.setNetworkAgent(vpnNetworkAgent);
mMockVpn.connect();
mMockVpn.setUids(vpnRange);
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 114e0fa21296..0ef224a5f8ee 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -481,12 +481,14 @@ public class WifiConfiguration implements Parcelable {
allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
break;
case SECURITY_TYPE_SAE:
+ allowedProtocols.set(WifiConfiguration.Protocol.RSN);
allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
requirePMF = true;
break;
case SECURITY_TYPE_EAP_SUITE_B:
+ allowedProtocols.set(WifiConfiguration.Protocol.RSN);
allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256);
allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
@@ -496,6 +498,7 @@ public class WifiConfiguration implements Parcelable {
requirePMF = true;
break;
case SECURITY_TYPE_OWE:
+ allowedProtocols.set(WifiConfiguration.Protocol.RSN);
allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);