summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp5
-rw-r--r--TEST_MAPPING16
-rw-r--r--apex/statsd/aidl/android/os/IStatsManager.aidl2
-rw-r--r--apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java62
-rw-r--r--api/current.txt2
-rw-r--r--api/system-current.txt66
-rw-r--r--cmds/statsd/src/StatsService.cpp8
-rw-r--r--cmds/statsd/src/StatsService.h4
-rw-r--r--cmds/statsd/src/atoms.proto38
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.cpp3
-rw-r--r--core/java/android/app/INotificationManager.aidl2
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java84
-rw-r--r--core/java/android/app/admin/DevicePolicyManagerInternal.java9
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl4
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java101
-rwxr-xr-xcore/java/android/bluetooth/BluetoothA2dpSink.java2
-rw-r--r--core/java/android/bluetooth/BluetoothCodecConfig.java179
-rw-r--r--core/java/android/bluetooth/BluetoothCodecStatus.java42
-rw-r--r--core/java/android/os/UserManager.java94
-rw-r--r--core/java/android/os/connectivity/WifiActivityEnergyInfo.java32
-rw-r--r--core/java/android/provider/MediaStore.java12
-rw-r--r--core/java/android/provider/Telephony.java19
-rw-r--r--core/java/android/util/StatsLog.java6
-rw-r--r--core/java/android/view/ViewRootImpl.java2
-rw-r--r--core/java/android/widget/RemoteViews.java23
-rw-r--r--core/java/com/android/internal/os/RuntimeInit.java5
-rw-r--r--core/java/com/android/internal/widget/ILockSettings.aidl2
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java30
-rw-r--r--core/java/com/android/server/BootReceiver.java40
-rw-r--r--core/jni/AndroidRuntime.cpp9
-rw-r--r--core/proto/android/service/notification.proto11
-rw-r--r--data/etc/privapp-permissions-platform.xml5
-rw-r--r--media/java/android/media/tv/tuner/FilterSettings.java383
-rw-r--r--media/java/android/media/tv/tuner/Tuner.java15
-rw-r--r--media/java/android/media/tv/tuner/TunerConstants.java11
-rw-r--r--media/jni/Android.bp2
-rw-r--r--media/jni/android_media_tv_Tuner.cpp159
-rw-r--r--media/jni/android_media_tv_Tuner.h18
-rw-r--r--media/jni/soundpool/StreamManager.cpp3
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java14
-rw-r--r--packages/SystemUI/TEST_MAPPING6
-rw-r--r--packages/SystemUI/res/layout/bubble_menu_view.xml43
-rw-r--r--packages/SystemUI/res/values-television/config.xml39
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java106
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleMenuView.java81
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java64
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java27
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java12
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java13
-rw-r--r--services/core/java/com/android/server/PackageWatchdog.java31
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java6
-rw-r--r--services/core/java/com/android/server/am/BatteryExternalStatsWorker.java2
-rw-r--r--services/core/java/com/android/server/integrity/model/BitInputStream.java55
-rw-r--r--services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java16
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java6
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java6
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java155
-rw-r--r--services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java9
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java67
-rw-r--r--services/core/java/com/android/server/notification/NotificationUsageStats.java54
-rw-r--r--services/core/java/com/android/server/notification/PulledStats.java129
-rw-r--r--services/core/java/com/android/server/pm/ApexManager.java46
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java4
-rw-r--r--services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java57
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java25
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java1
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java5
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java277
-rw-r--r--services/java/com/android/server/SystemServer.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java71
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java21
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java151
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java49
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java20
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java39
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java2
-rw-r--r--services/tests/uiservicestests/Android.bp1
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PulledStatsTest.java113
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsDatabase.java36
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java18
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java3
-rw-r--r--tests/FlickerTests/AndroidTest.xml2
-rw-r--r--tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java132
-rw-r--r--tools/aapt2/java/JavaClassGenerator.cpp8
-rw-r--r--tools/stats_log_api_gen/java_writer.cpp13
-rw-r--r--wifi/java/android/net/wifi/IWifiManager.aidl3
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java19
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkSuggestion.java49
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareManager.java12
-rw-r--r--wifi/java/com/android/server/wifi/BaseWifiService.java5
-rw-r--r--wifi/tests/src/android/net/wifi/WifiManagerTest.java14
-rw-r--r--wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java67
95 files changed, 2662 insertions, 1087 deletions
diff --git a/Android.bp b/Android.bp
index 3dd8a0a66b14..8daee86c6ac2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1680,16 +1680,13 @@ filegroup {
}
filegroup {
- name: "framework-wifistack-shared-srcs",
+ name: "framework-wifi-service-shared-srcs",
srcs: [
":framework-annotations",
"core/java/android/os/HandlerExecutor.java",
"core/java/android/util/BackupUtils.java",
- "core/java/android/util/KeyValueListParser.java",
"core/java/android/util/LocalLog.java",
"core/java/android/util/Rational.java",
- "core/java/android/util/proto/ProtoStream.java",
- "core/java/android/util/proto/ProtoOutputStream.java",
"core/java/com/android/internal/util/FastXmlSerializer.java",
"core/java/com/android/internal/util/HexDump.java",
"core/java/com/android/internal/util/IState.java",
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 55fa5ed13d79..b1c4cad72dc9 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -7,6 +7,22 @@
"exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
+ },
+ {
+ "name": "ExtServicesUnitTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "TestablesTests",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
}
],
"postsubmit-managedprofile-stress": [
diff --git a/apex/statsd/aidl/android/os/IStatsManager.aidl b/apex/statsd/aidl/android/os/IStatsManager.aidl
index 5ebb9f2e4e90..cc62f07a3750 100644
--- a/apex/statsd/aidl/android/os/IStatsManager.aidl
+++ b/apex/statsd/aidl/android/os/IStatsManager.aidl
@@ -240,7 +240,7 @@ interface IStatsManager {
* Logs an event for watchdog rollbacks.
*/
oneway void sendWatchdogRollbackOccurredAtom(in int rollbackType, in String packageName,
- in long packageVersionCode);
+ in long packageVersionCode, in int rollbackReason, in String failingPackageName);
/**
* Returns the most recently registered experiment IDs.
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 c9139b15f223..6fb3bc47859d 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -41,6 +41,7 @@ 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;
@@ -139,6 +140,7 @@ import com.android.server.LocalServices;
import com.android.server.SystemService;
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.IonMemoryUtil.IonAllocations;
import com.android.server.stats.ProcfsMemoryUtil.MemorySnapshot;
@@ -1750,14 +1752,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
if (statsFiles.size() != 1) {
return;
}
- InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(
- statsFiles.get(0));
- int[] len = new int[1];
- byte[] stats = readFully(stream, len);
- StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
- wallClockNanos);
- e.writeStorage(Arrays.copyOf(stats, len[0]));
- pulledData.add(e);
+ unpackStreamedData(tagId, elapsedNanos, wallClockNanos, pulledData, statsFiles);
new File(mBaseDir.getAbsolutePath() + "/" + section + "_"
+ lastHighWaterMark).delete();
new File(
@@ -1773,6 +1768,52 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
}
+ private INotificationManager mNotificationManager =
+ INotificationManager.Stub.asInterface(
+ ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+
+ private void pullNotificationStats(int reportId, int tagId, long elapsedNanos,
+ long wallClockNanos,
+ List<StatsLogEventWrapper> pulledData) {
+ final long callingToken = Binder.clearCallingIdentity();
+ try {
+ // determine last pull tine. Copy file trick from pullProcessStats?
+ long lastNotificationStatsNs = wallClockNanos -
+ TimeUnit.NANOSECONDS.convert(1, TimeUnit.DAYS);
+
+ List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
+ long notificationStatsNs = mNotificationManager.pullStats(
+ lastNotificationStatsNs, reportId, true, statsFiles);
+ if (statsFiles.size() != 1) {
+ return;
+ }
+ unpackStreamedData(tagId, elapsedNanos, wallClockNanos, pulledData, statsFiles);
+ } catch (IOException e) {
+ Log.e(TAG, "Getting notistats failed: ", e);
+
+ } catch (RemoteException e) {
+ Log.e(TAG, "Getting notistats failed: ", e);
+ } catch (SecurityException e) {
+ Log.e(TAG, "Getting notistats failed: ", e);
+ } finally {
+ Binder.restoreCallingIdentity(callingToken);
+ }
+
+ }
+
+ static void unpackStreamedData(int tagId, long elapsedNanos, long wallClockNanos,
+ List<StatsLogEventWrapper> pulledData, List<ParcelFileDescriptor> statsFiles)
+ throws IOException {
+ InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(
+ statsFiles.get(0));
+ int[] len = new int[1];
+ byte[] stats = readFully(stream, len);
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos,
+ wallClockNanos);
+ e.writeStorage(Arrays.copyOf(stats, len[0]));
+ pulledData.add(e);
+ }
+
static byte[] readFully(InputStream stream, int[] outLen) throws IOException {
int pos = 0;
final int initialAvail = stream.available();
@@ -2621,6 +2662,11 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
pullAppOps(elapsedNanos, wallClockNanos, ret);
break;
}
+ case StatsLog.NOTIFICATION_REMOTE_VIEWS: {
+ pullNotificationStats(NotificationManagerService.REPORT_REMOTE_VIEWS,
+ tagId, elapsedNanos, wallClockNanos, ret);
+ break;
+ }
default:
Slog.w(TAG, "No such tagId data as " + tagId);
return null;
diff --git a/api/current.txt b/api/current.txt
index 4c4895c5bcb6..d05ef8cea53a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6834,7 +6834,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 boolean resetPassword(String, int);
+ 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);
method @Nullable public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(@NonNull android.content.ComponentName);
diff --git a/api/system-current.txt b/api/system-current.txt
index e46c60f5ec47..217943c519af 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1331,8 +1331,22 @@ package android.app.usage {
package android.bluetooth {
public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void disableOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void enableOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice);
+ method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothDevice getActiveDevice();
+ method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothCodecStatus getCodecStatus(@Nullable android.bluetooth.BluetoothDevice);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int getOptionalCodecsEnabled(@Nullable android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setCodecConfigPreference(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothCodecConfig);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void setOptionalCodecsEnabled(@Nullable android.bluetooth.BluetoothDevice, int);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public int supportsOptionalCodecs(@Nullable android.bluetooth.BluetoothDevice);
+ field public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0; // 0x0
+ field public static final int OPTIONAL_CODECS_PREF_DISABLED = 0; // 0x0
+ field public static final int OPTIONAL_CODECS_PREF_ENABLED = 1; // 0x1
+ field public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1; // 0xffffffff
+ field public static final int OPTIONAL_CODECS_SUPPORTED = 1; // 0x1
+ field public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1; // 0xffffffff
}
public final class BluetoothAdapter {
@@ -1361,6 +1375,52 @@ package android.bluetooth {
method public void onMetadataChanged(@NonNull android.bluetooth.BluetoothDevice, int, @Nullable byte[]);
}
+ public final class BluetoothCodecConfig implements android.os.Parcelable {
+ ctor public BluetoothCodecConfig(int, int, int, int, int, long, long, long, long);
+ ctor public BluetoothCodecConfig(int);
+ method public int getBitsPerSample();
+ method @NonNull public String getCodecName();
+ method public int getCodecPriority();
+ method public long getCodecSpecific1();
+ method public int getCodecType();
+ method public int getSampleRate();
+ method public boolean isMandatoryCodec();
+ field public static final int BITS_PER_SAMPLE_16 = 1; // 0x1
+ field public static final int BITS_PER_SAMPLE_24 = 2; // 0x2
+ field public static final int BITS_PER_SAMPLE_32 = 4; // 0x4
+ field public static final int BITS_PER_SAMPLE_NONE = 0; // 0x0
+ field public static final int CHANNEL_MODE_MONO = 1; // 0x1
+ field public static final int CHANNEL_MODE_NONE = 0; // 0x0
+ field public static final int CHANNEL_MODE_STEREO = 2; // 0x2
+ field public static final int CODEC_PRIORITY_DEFAULT = 0; // 0x0
+ field public static final int CODEC_PRIORITY_DISABLED = -1; // 0xffffffff
+ field public static final int CODEC_PRIORITY_HIGHEST = 1000000; // 0xf4240
+ field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecConfig> CREATOR;
+ field public static final int SAMPLE_RATE_176400 = 16; // 0x10
+ field public static final int SAMPLE_RATE_192000 = 32; // 0x20
+ field public static final int SAMPLE_RATE_44100 = 1; // 0x1
+ field public static final int SAMPLE_RATE_48000 = 2; // 0x2
+ field public static final int SAMPLE_RATE_88200 = 4; // 0x4
+ field public static final int SAMPLE_RATE_96000 = 8; // 0x8
+ field public static final int SAMPLE_RATE_NONE = 0; // 0x0
+ field public static final int SOURCE_CODEC_TYPE_AAC = 1; // 0x1
+ field public static final int SOURCE_CODEC_TYPE_APTX = 2; // 0x2
+ field public static final int SOURCE_CODEC_TYPE_APTX_HD = 3; // 0x3
+ field public static final int SOURCE_CODEC_TYPE_INVALID = 1000000; // 0xf4240
+ field public static final int SOURCE_CODEC_TYPE_LDAC = 4; // 0x4
+ field public static final int SOURCE_CODEC_TYPE_MAX = 5; // 0x5
+ field public static final int SOURCE_CODEC_TYPE_SBC = 0; // 0x0
+ }
+
+ public final class BluetoothCodecStatus implements android.os.Parcelable {
+ ctor public BluetoothCodecStatus(@Nullable android.bluetooth.BluetoothCodecConfig, @Nullable android.bluetooth.BluetoothCodecConfig[], @Nullable android.bluetooth.BluetoothCodecConfig[]);
+ method @Nullable public android.bluetooth.BluetoothCodecConfig getCodecConfig();
+ method @Nullable public android.bluetooth.BluetoothCodecConfig[] getCodecsLocalCapabilities();
+ method @Nullable public android.bluetooth.BluetoothCodecConfig[] getCodecsSelectableCapabilities();
+ field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecStatus> CREATOR;
+ field public static final String EXTRA_CODEC_STATUS = "android.bluetooth.extra.CODEC_STATUS";
+ }
+
public final class BluetoothDevice implements android.os.Parcelable {
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean cancelBondProcess();
method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public byte[] getMetadata(int);
@@ -6624,7 +6684,7 @@ package android.os.connectivity {
}
public final class WifiActivityEnergyInfo implements android.os.Parcelable {
- ctor public WifiActivityEnergyInfo(long, int, long, long, long, long, long);
+ ctor public WifiActivityEnergyInfo(long, int, long, long, long, long);
method public int describeContents();
method public long getControllerEnergyUsedMicroJoules();
method public long getControllerIdleDurationMillis();
@@ -7243,6 +7303,10 @@ package android.provider {
field public static final String SUB_ID = "sub_id";
}
+ public static final class Telephony.SimInfo {
+ field @NonNull public static final android.net.Uri CONTENT_URI;
+ }
+
public static final class Telephony.Sms.Intents {
field public static final String ACTION_SMS_EMERGENCY_CB_RECEIVED = "android.provider.action.SMS_EMERGENCY_CB_RECEIVED";
}
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index d10a661c6d83..3c5ad4231133 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1417,7 +1417,10 @@ Status StatsService::sendBinaryPushStateChangedAtom(const android::String16& tra
Status StatsService::sendWatchdogRollbackOccurredAtom(const int32_t rollbackTypeIn,
const android::String16& packageNameIn,
- const int64_t packageVersionCodeIn) {
+ const int64_t packageVersionCodeIn,
+ const int32_t rollbackReasonIn,
+ const android::String16&
+ failingPackageNameIn) {
// Note: We skip the usage stats op check here since we do not have a package name.
// This is ok since we are overloading the usage_stats permission.
// This method only sends data, it does not receive it.
@@ -1439,7 +1442,8 @@ Status StatsService::sendWatchdogRollbackOccurredAtom(const int32_t rollbackType
}
android::util::stats_write(android::util::WATCHDOG_ROLLBACK_OCCURRED,
- rollbackTypeIn, String8(packageNameIn).string(), packageVersionCodeIn);
+ rollbackTypeIn, String8(packageNameIn).string(), packageVersionCodeIn,
+ rollbackReasonIn, String8(failingPackageNameIn).string());
// Fast return to save disk read.
if (rollbackTypeIn != android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 8c98e7b96936..50b1014f4e8a 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -214,7 +214,9 @@ public:
virtual Status sendWatchdogRollbackOccurredAtom(
const int32_t rollbackTypeIn,
const android::String16& packageNameIn,
- const int64_t packageVersionCodeIn) override;
+ const int64_t packageVersionCodeIn,
+ const int32_t rollbackReasonIn,
+ const android::String16& failingPackageNameIn) override;
/**
* Binder call to get registered experiment IDs.
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 2efb78943812..f1ea4c9e0c68 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -112,7 +112,7 @@ message Atom {
TouchEventReported touch_event_reported = 34;
WakeupAlarmOccurred wakeup_alarm_occurred = 35;
KernelWakeupReported kernel_wakeup_reported = 36;
- WifiLockStateChanged wifi_lock_state_changed = 37;
+ WifiLockStateChanged wifi_lock_state_changed = 37 [(log_from_module) = "wifi"];
WifiSignalStrengthChanged wifi_signal_strength_changed = 38;
WifiScanStateChanged wifi_scan_state_changed = 39;
PhoneSignalStrengthChanged phone_signal_strength_changed = 40;
@@ -356,7 +356,7 @@ message Atom {
}
// Pulled events will start at field 10000.
- // Next: 10065
+ // Next: 10067
oneof pulled {
WifiBytesTransfer wifi_bytes_transfer = 10000;
WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001;
@@ -423,6 +423,7 @@ message Atom {
SurfaceflingerStatsLayerInfo surfaceflinger_stats_layer_info = 10063;
ProcessMemorySnapshot process_memory_snapshot = 10064;
VmsClientStats vms_client_stats = 10065;
+ NotificationRemoteViews notification_remote_views = 10066;
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -1742,6 +1743,19 @@ message WatchdogRollbackOccurred {
optional string package_name = 2;
optional int32 package_version_code = 3;
+
+ enum RollbackReasonType {
+ REASON_UNKNOWN = 0;
+ REASON_NATIVE_CRASH = 1;
+ REASON_EXPLICIT_HEALTH_CHECK = 2;
+ REASON_APP_CRASH = 3;
+ REASON_APP_NOT_RESPONDING = 4;
+ }
+ optional RollbackReasonType rollback_reason = 4;
+
+ // Set by RollbackPackageHealthObserver to be the package that is failing when a rollback
+ // is initiated. Empty if the package is unknown.
+ optional string failing_package_name = 5;
}
/**
@@ -4947,6 +4961,24 @@ message ProcStatsPkgProc {
optional ProcessStatsSectionProto proc_stats_section = 1;
}
+// Next Tag: 2
+message PackageRemoteViewInfoProto {
+ optional string package_name = 1;
+ // add per-package additional info here (like channels)
+}
+
+// Next Tag: 2
+message NotificationRemoteViewsProto {
+ repeated PackageRemoteViewInfoProto package_remote_view_info = 1;
+}
+
+/**
+ * Pulled from NotificationManagerService.java
+ */
+message NotificationRemoteViews {
+ optional NotificationRemoteViewsProto notification_remote_views = 1;
+}
+
message PowerProfileProto {
optional double cpu_suspend = 1;
@@ -5960,6 +5992,8 @@ message PermissionGrantRequestResultReported {
IGNORED_RESTRICTED_PERMISSION = 9;
// one time permission was granted by user action
USER_GRANTED_ONE_TIME = 10;
+ // user ignored request by leaving the request screen without choosing any option
+ USER_IGNORED = 11;
}
// The result of the permission grant
optional Result result = 6;
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index b5bad0530503..615af89e3186 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -281,6 +281,9 @@ std::map<PullerKey, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
{{.atomTag = android::util::VMS_CLIENT_STATS},
{.additiveFields = {5, 6, 7, 8, 9, 10},
.puller = new CarStatsPuller(android::util::VMS_CLIENT_STATS)}},
+ // NotiifcationRemoteViews.
+ {{.atomTag = android::util::NOTIFICATION_REMOTE_VIEWS},
+ {.puller = new StatsCompanionServicePuller(android::util::NOTIFICATION_REMOTE_VIEWS)}},
};
StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 0957dba4eac1..86f52af1a13b 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -207,4 +207,6 @@ interface INotificationManager
void setPrivateNotificationsAllowed(boolean allow);
boolean getPrivateNotificationsAllowed();
+
+ long pullStats(long startNs, int report, boolean doAgg, out List<ParcelFileDescriptor> stats);
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 34ceb08f39bf..915e4572c035 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3742,17 +3742,35 @@ public class DevicePolicyManager {
/**
* Force a new password for device unlock (the password needed to access the entire device) or
* the work profile challenge on the current user. This takes effect immediately.
- * <p>
- * <em>For device owner and profile owners targeting SDK level
- * {@link android.os.Build.VERSION_CODES#O} or above, this API is no longer available and will
- * throw {@link SecurityException}. Please use the new API {@link #resetPasswordWithToken}
- * instead. </em>
- * <p>
- * <em>Note: This API has been limited as of {@link android.os.Build.VERSION_CODES#N} for
- * device admins that are not device owner and not profile owner.
- * The password can now only be changed if there is currently no password set. Device owner
- * and profile owner can still do this when user is unlocked and does not have a managed
- * profile.</em>
+ *
+ * <p> Before {@link android.os.Build.VERSION_CODES#N}, this API is available to device admin,
+ * profile owner and device owner. Starting from {@link android.os.Build.VERSION_CODES#N},
+ * legacy device admin (who is not also profile owner or device owner) can only call this
+ * API to set a new password if there is currently no password set. Profile owner and device
+ * owner can continue to force change an existing password as long as the target user is
+ * unlocked, although device owner will not be able to call this API at all if there is also a
+ * managed profile on the device.
+ *
+ * <p> Between {@link android.os.Build.VERSION_CODES#O},
+ * {@link android.os.Build.VERSION_CODES#P} and {@link android.os.Build.VERSION_CODES#Q},
+ * profile owner and devices owner targeting SDK level {@link android.os.Build.VERSION_CODES#O}
+ * or above who attempt to call this API will receive {@link SecurityException}; they are
+ * encouraged to migrate to the new {@link #resetPasswordWithToken} API instead.
+ * Profile owner and device owner targeting older SDK levels are not affected: they continue
+ * to experience the existing behaviour described in the previous paragraph.
+ *
+ * <p><em>Starting from {@link android.os.Build.VERSION_CODES#R}, this API is no longer
+ * supported in most cases.</em> Device owner and profile owner calling
+ * this API will receive {@link SecurityException} if they target SDK level
+ * {@link android.os.Build.VERSION_CODES#O} or above, or they will receive a silent failure
+ * (API returning {@code false}) if they target lower SDK level.
+ * For legacy device admins, this API throws {@link SecurityException} if they target SDK level
+ * {@link android.os.Build.VERSION_CODES#N} or above, and returns {@code false} otherwise. Only
+ * privileged apps holding RESET_PASSWORD permission which are part of
+ * the system factory image can still call this API to set a new password if there is currently
+ * no password set. In this case, if the device already has a password, this API will throw
+ * {@link SecurityException}.
+ *
* <p>
* The given password must be sufficient for the current password quality and length constraints
* as returned by {@link #getPasswordQuality(ComponentName)} and
@@ -3760,12 +3778,7 @@ public class DevicePolicyManager {
* it will be rejected and false returned. Note that the password may be a stronger quality
* (containing alphanumeric characters when the requested quality is only numeric), in which
* case the currently active quality will be increased to match.
- * <p>
- * Calling with a null or empty password will clear any existing PIN, pattern or password if the
- * current password constraints allow it. <em>Note: This will not work in
- * {@link android.os.Build.VERSION_CODES#N} and later for managed profiles, or for device admins
- * that are not device owner or profile owner. Once set, the password cannot be changed to null
- * or empty except by these admins.</em>
+ *
* <p>On devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, this
* methods does nothing.
* <p>
@@ -3777,11 +3790,13 @@ public class DevicePolicyManager {
* @param flags May be 0 or combination of {@link #RESET_PASSWORD_REQUIRE_ENTRY} and
* {@link #RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT}.
* @return Returns true if the password was applied, or false if it is not acceptable for the
- * current constraints or if the user has not been decrypted yet.
+ * current constraints.
* @throws SecurityException if the calling application does not own an active administrator
* that uses {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD}
* @throws IllegalStateException if the calling user is locked or has a managed profile.
+ * @deprecated Please use {@link #resetPasswordWithToken} instead.
*/
+ @Deprecated
@RequiresFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN)
public boolean resetPassword(String password, int flags) {
throwIfParentInstance("resetPassword");
@@ -5555,7 +5570,12 @@ public class DevicePolicyManager {
* device, for this user. After setting this, no applications running as this user will be able
* to access any cameras on the device.
* <p>
- * If the caller is device owner, then the restriction will be applied to all users.
+ * This method can be called on the {@link DevicePolicyManager} instance,
+ * returned by {@link #getParentProfileInstance(ComponentName)}, where the caller must be
+ * the profile owner of an organization-owned managed profile.
+ * <p>
+ * If the caller is device owner or called on the parent instance, then the
+ * restriction will be applied to all users.
* <p>
* The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA} to be able to call this method; if it has
@@ -5567,10 +5587,9 @@ public class DevicePolicyManager {
* {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA}.
*/
public void setCameraDisabled(@NonNull ComponentName admin, boolean disabled) {
- throwIfParentInstance("setCameraDisabled");
if (mService != null) {
try {
- mService.setCameraDisabled(admin, disabled);
+ mService.setCameraDisabled(admin, disabled, mParentInstance);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -5580,11 +5599,15 @@ public class DevicePolicyManager {
/**
* Determine whether or not the device's cameras have been disabled for this user,
* either by the calling admin, if specified, or all admins.
+ * <p>
+ * This method can be called on the {@link DevicePolicyManager} instance,
+ * returned by {@link #getParentProfileInstance(ComponentName)}, where the caller must be
+ * the profile owner of an organization-owned managed profile.
+ *
* @param admin The name of the admin component to check, or {@code null} to check whether any admins
* have disabled the camera
*/
public boolean getCameraDisabled(@Nullable ComponentName admin) {
- throwIfParentInstance("getCameraDisabled");
return getCameraDisabled(admin, myUserId());
}
@@ -5593,7 +5616,7 @@ public class DevicePolicyManager {
public boolean getCameraDisabled(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
- return mService.getCameraDisabled(admin, userHandle);
+ return mService.getCameraDisabled(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -7893,7 +7916,8 @@ public class DevicePolicyManager {
* for the list of keys.
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
- public void addUserRestriction(@NonNull ComponentName admin, String key) {
+ public void addUserRestriction(@NonNull ComponentName admin,
+ @UserManager.UserRestrictionKey String key) {
throwIfParentInstance("addUserRestriction");
if (mService != null) {
try {
@@ -7915,7 +7939,8 @@ public class DevicePolicyManager {
* for the list of keys.
* @throws SecurityException if {@code admin} is not a device or profile owner.
*/
- public void clearUserRestriction(@NonNull ComponentName admin, String key) {
+ public void clearUserRestriction(@NonNull ComponentName admin,
+ @UserManager.UserRestrictionKey String key) {
throwIfParentInstance("clearUserRestriction");
if (mService != null) {
try {
@@ -9344,7 +9369,6 @@ public class DevicePolicyManager {
* <li>{@link #setPasswordExpirationTimeout}</li>
* <li>{@link #getPasswordExpiration}</li>
* <li>{@link #getPasswordMaximumLength}</li>
- * <li>{@link #getPasswordComplexity}</li>
* <li>{@link #isActivePasswordSufficient}</li>
* <li>{@link #getCurrentFailedPasswordAttempts}</li>
* <li>{@link #getMaximumFailedPasswordsForWipe}</li>
@@ -9359,6 +9383,14 @@ public class DevicePolicyManager {
* <li>{@link #getRequiredStrongAuthTimeout}</li>
* <li>{@link #setRequiredStrongAuthTimeout}</li>
* </ul>
+ * <p>
+ * The following methods are supported for the parent instance but can only be called by the
+ * profile owner of a managed profile that was created during the device provisioning flow:
+ * <ul>
+ * <li>{@link #getPasswordComplexity}</li>
+ * <li>{@link #setCameraDisabled}</li>
+ * <li>{@link #getCameraDisabled}</li>
+ * </ul>
*
* <p>The following methods can be called by the profile owner of a managed profile
* on an organization-owned device:
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 713126ee9341..f299d456a18f 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -145,15 +145,6 @@ public abstract class DevicePolicyManagerInternal {
public abstract void reportSeparateProfileChallengeChanged(@UserIdInt int userId);
/**
- * Check whether the user could have their password reset in an untrusted manor due to there
- * being an admin which can call {@link #resetPassword} to reset the password without knowledge
- * of the previous password.
- *
- * @param userId The user in question
- */
- public abstract boolean canUserHaveUntrustedCredentialReset(@UserIdInt int userId);
-
- /**
* Return text of error message if printing is disabled.
* Called by Print Service when printing is disabled by PO or DO when printing is attempted.
*
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index f55026c76906..34246fa808bd 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -114,8 +114,8 @@ interface IDevicePolicyManager {
boolean requestBugreport(in ComponentName who);
- void setCameraDisabled(in ComponentName who, boolean disabled);
- boolean getCameraDisabled(in ComponentName who, int userHandle);
+ void setCameraDisabled(in ComponentName who, boolean disabled, boolean parent);
+ boolean getCameraDisabled(in ComponentName who, int userHandle, boolean parent);
void setScreenCaptureDisabled(in ComponentName who, boolean disabled);
boolean getScreenCaptureDisabled(in ComponentName who, int userHandle);
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 8ed61b6c87e3..64df0e84f6dc 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.Manifest;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -32,6 +33,8 @@ import android.os.ParcelUuid;
import android.os.RemoteException;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
@@ -154,13 +157,22 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
public static final int STATE_NOT_PLAYING = 11;
+ /** @hide */
+ @IntDef(prefix = "OPTIONAL_CODECS_", value = {
+ OPTIONAL_CODECS_SUPPORT_UNKNOWN,
+ OPTIONAL_CODECS_NOT_SUPPORTED,
+ OPTIONAL_CODECS_SUPPORTED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface OptionalCodecsSupportStatus {}
+
/**
* We don't have a stored preference for whether or not the given A2DP sink device supports
* optional codecs.
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1;
/**
@@ -168,7 +180,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0;
/**
@@ -176,16 +188,25 @@ public final class BluetoothA2dp implements BluetoothProfile {
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_SUPPORTED = 1;
+ /** @hide */
+ @IntDef(prefix = "OPTIONAL_CODECS_PREF_", value = {
+ OPTIONAL_CODECS_PREF_UNKNOWN,
+ OPTIONAL_CODECS_PREF_DISABLED,
+ OPTIONAL_CODECS_PREF_ENABLED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface OptionalCodecsPreferenceStatus {}
+
/**
- * We don't have a stored preference for whether optional codecs should be enabled or disabled
- * for the given A2DP device.
+ * We don't have a stored preference for whether optional codecs should be enabled or
+ * disabled for the given A2DP device.
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1;
/**
@@ -193,7 +214,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_PREF_DISABLED = 0;
/**
@@ -201,7 +222,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public static final int OPTIONAL_CODECS_PREF_ENABLED = 1;
private BluetoothAdapter mAdapter;
@@ -248,13 +269,12 @@ public final class BluetoothA2dp implements BluetoothProfile {
* the state. Users can get the connection state of the profile
* from this intent.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
*
* @param device Remote Bluetooth Device
* @return false on immediate error, true otherwise
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
@UnsupportedAppUsage
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
@@ -289,13 +309,12 @@ public final class BluetoothA2dp implements BluetoothProfile {
* {@link #STATE_DISCONNECTING} can be used to distinguish between the
* two scenarios.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
*
* @param device Remote Bluetooth Device
* @return false on immediate error, true otherwise
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
@@ -384,14 +403,12 @@ public final class BluetoothA2dp implements BluetoothProfile {
* {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
* with the active device.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
- *
* @param device the remote Bluetooth device. Could be null to clear
* the active device and stop streaming audio to a Bluetooth device.
* @return false on immediate error, true otherwise
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
@UnsupportedAppUsage
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) log("setActiveDevice(" + device + ")");
@@ -412,16 +429,13 @@ public final class BluetoothA2dp implements BluetoothProfile {
/**
* Get the connected device that is active.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
- * permission.
- *
* @return the connected device that is active or null if no device
* is active
* @hide
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @SystemApi
@Nullable
- @UnsupportedAppUsage
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public BluetoothDevice getActiveDevice() {
if (VDBG) log("getActiveDevice()");
try {
@@ -441,7 +455,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
* Set priority of the profile
*
* <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
+ * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF}
*
* @param device Paired bluetooth device
* @param priority
@@ -626,8 +640,10 @@ public final class BluetoothA2dp implements BluetoothProfile {
* @return the current codec status
* @hide
*/
- @UnsupportedAppUsage
- public @Nullable BluetoothCodecStatus getCodecStatus(BluetoothDevice device) {
+ @SystemApi
+ @Nullable
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public BluetoothCodecStatus getCodecStatus(@Nullable BluetoothDevice device) {
if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")");
try {
final IBluetoothA2dp service = getService();
@@ -652,9 +668,10 @@ public final class BluetoothA2dp implements BluetoothProfile {
* @param codecConfig the codec configuration preference
* @hide
*/
- @UnsupportedAppUsage
- public void setCodecConfigPreference(BluetoothDevice device,
- BluetoothCodecConfig codecConfig) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void setCodecConfigPreference(@Nullable BluetoothDevice device,
+ @Nullable BluetoothCodecConfig codecConfig) {
if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")");
try {
final IBluetoothA2dp service = getService();
@@ -676,8 +693,9 @@ public final class BluetoothA2dp implements BluetoothProfile {
* active A2DP Bluetooth device.
* @hide
*/
- @UnsupportedAppUsage
- public void enableOptionalCodecs(BluetoothDevice device) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void enableOptionalCodecs(@Nullable BluetoothDevice device) {
if (DBG) Log.d(TAG, "enableOptionalCodecs(" + device + ")");
enableDisableOptionalCodecs(device, true);
}
@@ -689,8 +707,9 @@ public final class BluetoothA2dp implements BluetoothProfile {
* active A2DP Bluetooth device.
* @hide
*/
- @UnsupportedAppUsage
- public void disableOptionalCodecs(BluetoothDevice device) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void disableOptionalCodecs(@Nullable BluetoothDevice device) {
if (DBG) Log.d(TAG, "disableOptionalCodecs(" + device + ")");
enableDisableOptionalCodecs(device, false);
}
@@ -728,8 +747,10 @@ public final class BluetoothA2dp implements BluetoothProfile {
* OPTIONAL_CODECS_SUPPORTED.
* @hide
*/
- @UnsupportedAppUsage
- public int supportsOptionalCodecs(BluetoothDevice device) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ @OptionalCodecsSupportStatus
+ public int supportsOptionalCodecs(@Nullable BluetoothDevice device) {
try {
final IBluetoothA2dp service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
@@ -738,7 +759,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
if (service == null) Log.w(TAG, "Proxy not attached to service");
return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
} catch (RemoteException e) {
- Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
+ Log.e(TAG, "Error talking to BT service in supportsOptionalCodecs()", e);
return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
}
}
@@ -751,8 +772,10 @@ public final class BluetoothA2dp implements BluetoothProfile {
* OPTIONAL_CODECS_PREF_DISABLED.
* @hide
*/
- @UnsupportedAppUsage
- public int getOptionalCodecsEnabled(BluetoothDevice device) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ @OptionalCodecsPreferenceStatus
+ public int getOptionalCodecsEnabled(@Nullable BluetoothDevice device) {
try {
final IBluetoothA2dp service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
@@ -761,7 +784,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
if (service == null) Log.w(TAG, "Proxy not attached to service");
return OPTIONAL_CODECS_PREF_UNKNOWN;
} catch (RemoteException e) {
- Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
+ Log.e(TAG, "Error talking to BT service in getOptionalCodecsEnabled()", e);
return OPTIONAL_CODECS_PREF_UNKNOWN;
}
}
@@ -775,8 +798,10 @@ public final class BluetoothA2dp implements BluetoothProfile {
* OPTIONAL_CODECS_PREF_DISABLED.
* @hide
*/
- @UnsupportedAppUsage
- public void setOptionalCodecsEnabled(BluetoothDevice device, int value) {
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void setOptionalCodecsEnabled(@Nullable BluetoothDevice device,
+ @OptionalCodecsPreferenceStatus int value) {
try {
if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN
&& value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index c17834aa8e52..cf3367602aa9 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -320,7 +320,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
* Set priority of the profile
*
* <p> The device should already be paired.
- * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
+ * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF}
*
* @param device Paired bluetooth device
* @param priority
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
index 36f3a1eeba79..08d0797997b5 100644
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -16,10 +16,15 @@
package android.bluetooth;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
@@ -29,78 +34,131 @@ import java.util.Objects;
*
* {@hide}
*/
+@SystemApi
public final class BluetoothCodecConfig implements Parcelable {
// Add an entry for each source codec here.
// NOTE: The values should be same as those listed in the following file:
// hardware/libhardware/include/hardware/bt_av.h
- @UnsupportedAppUsage
+
+ /** @hide */
+ @IntDef(prefix = "SOURCE_CODEC_TYPE_", value = {
+ SOURCE_CODEC_TYPE_SBC,
+ SOURCE_CODEC_TYPE_AAC,
+ SOURCE_CODEC_TYPE_APTX,
+ SOURCE_CODEC_TYPE_APTX_HD,
+ SOURCE_CODEC_TYPE_LDAC,
+ SOURCE_CODEC_TYPE_MAX,
+ SOURCE_CODEC_TYPE_INVALID
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SourceCodecType {}
+
public static final int SOURCE_CODEC_TYPE_SBC = 0;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_AAC = 1;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_APTX = 2;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_APTX_HD = 3;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_LDAC = 4;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_MAX = 5;
- @UnsupportedAppUsage
+
public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
- @UnsupportedAppUsage
+ /** @hide */
+ @IntDef(prefix = "CODEC_PRIORITY_", value = {
+ CODEC_PRIORITY_DISABLED,
+ CODEC_PRIORITY_DEFAULT,
+ CODEC_PRIORITY_HIGHEST
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CodecPriority {}
+
public static final int CODEC_PRIORITY_DISABLED = -1;
- @UnsupportedAppUsage
+
public static final int CODEC_PRIORITY_DEFAULT = 0;
- @UnsupportedAppUsage
+
public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
- @UnsupportedAppUsage
+
+ /** @hide */
+ @IntDef(prefix = "SAMPLE_RATE_", value = {
+ SAMPLE_RATE_NONE,
+ SAMPLE_RATE_44100,
+ SAMPLE_RATE_48000,
+ SAMPLE_RATE_88200,
+ SAMPLE_RATE_96000,
+ SAMPLE_RATE_176400,
+ SAMPLE_RATE_192000
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SampleRate {}
+
public static final int SAMPLE_RATE_NONE = 0;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_44100 = 0x1 << 0;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_48000 = 0x1 << 1;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_88200 = 0x1 << 2;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_96000 = 0x1 << 3;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_176400 = 0x1 << 4;
- @UnsupportedAppUsage
+
public static final int SAMPLE_RATE_192000 = 0x1 << 5;
- @UnsupportedAppUsage
+
+ /** @hide */
+ @IntDef(prefix = "BITS_PER_SAMPLE_", value = {
+ BITS_PER_SAMPLE_NONE,
+ BITS_PER_SAMPLE_16,
+ BITS_PER_SAMPLE_24,
+ BITS_PER_SAMPLE_32
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface BitsPerSample {}
+
public static final int BITS_PER_SAMPLE_NONE = 0;
- @UnsupportedAppUsage
+
public static final int BITS_PER_SAMPLE_16 = 0x1 << 0;
- @UnsupportedAppUsage
+
public static final int BITS_PER_SAMPLE_24 = 0x1 << 1;
- @UnsupportedAppUsage
+
public static final int BITS_PER_SAMPLE_32 = 0x1 << 2;
- @UnsupportedAppUsage
+
+ /** @hide */
+ @IntDef(prefix = "CHANNEL_MODE_", value = {
+ CHANNEL_MODE_NONE,
+ CHANNEL_MODE_MONO,
+ CHANNEL_MODE_STEREO
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ChannelMode {}
+
public static final int CHANNEL_MODE_NONE = 0;
- @UnsupportedAppUsage
+
public static final int CHANNEL_MODE_MONO = 0x1 << 0;
- @UnsupportedAppUsage
+
public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
- private final int mCodecType;
- private int mCodecPriority;
- private final int mSampleRate;
- private final int mBitsPerSample;
- private final int mChannelMode;
+ private final @SourceCodecType int mCodecType;
+ private @CodecPriority int mCodecPriority;
+ private final @SampleRate int mSampleRate;
+ private final @BitsPerSample int mBitsPerSample;
+ private final @ChannelMode int mChannelMode;
private final long mCodecSpecific1;
private final long mCodecSpecific2;
private final long mCodecSpecific3;
private final long mCodecSpecific4;
- @UnsupportedAppUsage
- public BluetoothCodecConfig(int codecType, int codecPriority,
- int sampleRate, int bitsPerSample,
- int channelMode, long codecSpecific1,
+ public BluetoothCodecConfig(@SourceCodecType int codecType, @CodecPriority int codecPriority,
+ @SampleRate int sampleRate, @BitsPerSample int bitsPerSample,
+ @ChannelMode int channelMode, long codecSpecific1,
long codecSpecific2, long codecSpecific3,
long codecSpecific4) {
mCodecType = codecType;
@@ -114,8 +172,7 @@ public final class BluetoothCodecConfig implements Parcelable {
mCodecSpecific4 = codecSpecific4;
}
- @UnsupportedAppUsage
- public BluetoothCodecConfig(int codecType) {
+ public BluetoothCodecConfig(@SourceCodecType int codecType) {
mCodecType = codecType;
mCodecPriority = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT;
mSampleRate = BluetoothCodecConfig.SAMPLE_RATE_NONE;
@@ -144,6 +201,12 @@ public final class BluetoothCodecConfig implements Parcelable {
return false;
}
+ /**
+ * Returns a hash based on the config values
+ *
+ * @return a hash based on the config values
+ * @hide
+ */
@Override
public int hashCode() {
return Objects.hash(mCodecType, mCodecPriority, mSampleRate,
@@ -155,6 +218,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Checks whether the object contains valid codec configuration.
*
* @return true if the object contains valid codec configuration, otherwise false.
+ * @hide
*/
public boolean isValid() {
return (mSampleRate != SAMPLE_RATE_NONE)
@@ -242,6 +306,12 @@ public final class BluetoothCodecConfig implements Parcelable {
+ ",mCodecSpecific4:" + mCodecSpecific4 + "}";
}
+ /**
+ * Always returns 0
+ *
+ * @return 0
+ * @hide
+ */
@Override
public int describeContents() {
return 0;
@@ -271,6 +341,14 @@ public final class BluetoothCodecConfig implements Parcelable {
}
};
+ /**
+ * Flattens the object to a parcel
+ *
+ * @param out The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written.
+ *
+ * @hide
+ */
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mCodecType);
@@ -289,7 +367,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @return the codec name
*/
- public String getCodecName() {
+ public @NonNull String getCodecName() {
switch (mCodecType) {
case SOURCE_CODEC_TYPE_SBC:
return "SBC";
@@ -315,8 +393,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @return the codec type
*/
- @UnsupportedAppUsage
- public int getCodecType() {
+ public @SourceCodecType int getCodecType() {
return mCodecType;
}
@@ -336,8 +413,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @return the codec priority
*/
- @UnsupportedAppUsage
- public int getCodecPriority() {
+ public @CodecPriority int getCodecPriority() {
return mCodecPriority;
}
@@ -347,9 +423,10 @@ public final class BluetoothCodecConfig implements Parcelable {
* means higher priority. If 0, reset to default.
*
* @param codecPriority the codec priority
+ * @hide
*/
@UnsupportedAppUsage
- public void setCodecPriority(int codecPriority) {
+ public void setCodecPriority(@CodecPriority int codecPriority) {
mCodecPriority = codecPriority;
}
@@ -366,8 +443,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @return the codec sample rate
*/
- @UnsupportedAppUsage
- public int getSampleRate() {
+ public @SampleRate int getSampleRate() {
return mSampleRate;
}
@@ -381,8 +457,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @return the codec bits per sample
*/
- @UnsupportedAppUsage
- public int getBitsPerSample() {
+ public @BitsPerSample int getBitsPerSample() {
return mBitsPerSample;
}
@@ -394,9 +469,10 @@ public final class BluetoothCodecConfig implements Parcelable {
* {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_STEREO}
*
* @return the codec channel mode
+ * @hide
*/
@UnsupportedAppUsage
- public int getChannelMode() {
+ public @ChannelMode int getChannelMode() {
return mChannelMode;
}
@@ -405,7 +481,6 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @return a codec specific value1.
*/
- @UnsupportedAppUsage
public long getCodecSpecific1() {
return mCodecSpecific1;
}
@@ -414,6 +489,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Gets a codec specific value2.
*
* @return a codec specific value2
+ * @hide
*/
@UnsupportedAppUsage
public long getCodecSpecific2() {
@@ -424,6 +500,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Gets a codec specific value3.
*
* @return a codec specific value3
+ * @hide
*/
@UnsupportedAppUsage
public long getCodecSpecific3() {
@@ -434,6 +511,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Gets a codec specific value4.
*
* @return a codec specific value4
+ * @hide
*/
@UnsupportedAppUsage
public long getCodecSpecific4() {
@@ -445,6 +523,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @param valueSet the value set presented by a bitmask
* @return true if the valueSet contains zero or single bit, otherwise false.
+ * @hide
*/
private static boolean hasSingleBit(int valueSet) {
return (valueSet == 0 || (valueSet & (valueSet - 1)) == 0);
@@ -454,6 +533,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Checks whether the object contains none or single sample rate.
*
* @return true if the object contains none or single sample rate, otherwise false.
+ * @hide
*/
public boolean hasSingleSampleRate() {
return hasSingleBit(mSampleRate);
@@ -463,6 +543,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Checks whether the object contains none or single bits per sample.
*
* @return true if the object contains none or single bits per sample, otherwise false.
+ * @hide
*/
public boolean hasSingleBitsPerSample() {
return hasSingleBit(mBitsPerSample);
@@ -472,6 +553,7 @@ public final class BluetoothCodecConfig implements Parcelable {
* Checks whether the object contains none or single channel mode.
*
* @return true if the object contains none or single channel mode, otherwise false.
+ * @hide
*/
public boolean hasSingleChannelMode() {
return hasSingleBit(mChannelMode);
@@ -482,6 +564,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @param other the codec config to compare against
* @return true if the audio feeding parameters are same, otherwise false
+ * @hide
*/
public boolean sameAudioFeedingParameters(BluetoothCodecConfig other) {
return (other != null && other.mSampleRate == mSampleRate
@@ -495,6 +578,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @param other the codec config to compare against
* @return true if the audio feeding parameters are similar, otherwise false.
+ * @hide
*/
public boolean similarCodecFeedingParameters(BluetoothCodecConfig other) {
if (other == null || mCodecType != other.mCodecType) {
@@ -526,6 +610,7 @@ public final class BluetoothCodecConfig implements Parcelable {
*
* @param other the codec config to compare against
* @return true if the codec specific parameters are the same, otherwise false.
+ * @hide
*/
public boolean sameCodecSpecificParameters(BluetoothCodecConfig other) {
if (other == null && mCodecType != other.mCodecType) {
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
index 58a764a85bed..b6e77391da5d 100644
--- a/core/java/android/bluetooth/BluetoothCodecStatus.java
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.java
@@ -17,7 +17,7 @@
package android.bluetooth;
import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,6 +32,7 @@ import java.util.Objects;
*
* {@hide}
*/
+@SystemApi
public final class BluetoothCodecStatus implements Parcelable {
/**
* Extra for the codec configuration intents of the individual profiles.
@@ -39,17 +40,16 @@ public final class BluetoothCodecStatus implements Parcelable {
* This extra represents the current codec status of the A2DP
* profile.
*/
- @UnsupportedAppUsage
public static final String EXTRA_CODEC_STATUS =
- "android.bluetooth.codec.extra.CODEC_STATUS";
+ "android.bluetooth.extra.CODEC_STATUS";
private final @Nullable BluetoothCodecConfig mCodecConfig;
private final BluetoothCodecConfig[] mCodecsLocalCapabilities;
private final BluetoothCodecConfig[] mCodecsSelectableCapabilities;
- public BluetoothCodecStatus(BluetoothCodecConfig codecConfig,
- BluetoothCodecConfig[] codecsLocalCapabilities,
- BluetoothCodecConfig[] codecsSelectableCapabilities) {
+ public BluetoothCodecStatus(@Nullable BluetoothCodecConfig codecConfig,
+ @Nullable BluetoothCodecConfig[] codecsLocalCapabilities,
+ @Nullable BluetoothCodecConfig[] codecsSelectableCapabilities) {
mCodecConfig = codecConfig;
mCodecsLocalCapabilities = codecsLocalCapabilities;
mCodecsSelectableCapabilities = codecsSelectableCapabilities;
@@ -74,6 +74,7 @@ public final class BluetoothCodecStatus implements Parcelable {
* @param c1 the first array of capabilities to compare
* @param c2 the second array of capabilities to compare
* @return true if both arrays contain same capabilities
+ * @hide
*/
public static boolean sameCapabilities(BluetoothCodecConfig[] c1,
BluetoothCodecConfig[] c2) {
@@ -95,6 +96,7 @@ public final class BluetoothCodecStatus implements Parcelable {
*
* @param codecConfig the codec config to compare against
* @return true if the codec config matches, otherwise false
+ * @hide
*/
public boolean isCodecConfigSelectable(BluetoothCodecConfig codecConfig) {
if (codecConfig == null || !codecConfig.hasSingleSampleRate()
@@ -125,7 +127,12 @@ public final class BluetoothCodecStatus implements Parcelable {
return false;
}
-
+ /**
+ * Returns a hash based on the codec config and local capabilities
+ *
+ * @return a hash based on the config values
+ * @hide
+ */
@Override
public int hashCode() {
return Objects.hash(mCodecConfig, mCodecsLocalCapabilities,
@@ -140,6 +147,12 @@ public final class BluetoothCodecStatus implements Parcelable {
+ "}";
}
+ /**
+ * Always returns 0
+ *
+ * @return 0
+ * @hide
+ */
@Override
public int describeContents() {
return 0;
@@ -165,6 +178,14 @@ public final class BluetoothCodecStatus implements Parcelable {
}
};
+ /**
+ * Flattens the object to a parcel
+ *
+ * @param out The Parcel in which the object should be written.
+ * @param flags Additional flags about how the object should be written.
+ *
+ * @hide
+ */
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeTypedObject(mCodecConfig, 0);
@@ -177,7 +198,6 @@ public final class BluetoothCodecStatus implements Parcelable {
*
* @return the current codec configuration
*/
- @UnsupportedAppUsage
public @Nullable BluetoothCodecConfig getCodecConfig() {
return mCodecConfig;
}
@@ -187,8 +207,7 @@ public final class BluetoothCodecStatus implements Parcelable {
*
* @return an array with the codecs local capabilities
*/
- @UnsupportedAppUsage
- public BluetoothCodecConfig[] getCodecsLocalCapabilities() {
+ public @Nullable BluetoothCodecConfig[] getCodecsLocalCapabilities() {
return mCodecsLocalCapabilities;
}
@@ -197,8 +216,7 @@ public final class BluetoothCodecStatus implements Parcelable {
*
* @return an array with the codecs selectable capabilities
*/
- @UnsupportedAppUsage
- public BluetoothCodecConfig[] getCodecsSelectableCapabilities() {
+ public @Nullable BluetoothCodecConfig[] getCodecsSelectableCapabilities() {
return mCodecsSelectableCapabilities;
}
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 9e9cd9218a0f..137f53782124 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -24,6 +24,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.StringDef;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
@@ -1112,6 +1113,82 @@ public class UserManager {
*/
public static final String KEY_RESTRICTIONS_PENDING = "restrictions_pending";
+ /**
+ * List of key values that can be passed into the various user restriction related methods
+ * in {@link UserManager} & {@link DevicePolicyManager}.
+ * Note: This is slightly different from the real set of user restrictions listed in {@link
+ * com.android.server.pm.UserRestrictionsUtils#USER_RESTRICTIONS}. For example
+ * {@link #KEY_RESTRICTIONS_PENDING} is not a real user restriction, but is a a legitimate
+ * value that can be passed into {@link #hasUserRestriction(String)}.
+ * @hide
+ */
+ @StringDef(value = {
+ DISALLOW_MODIFY_ACCOUNTS,
+ DISALLOW_CONFIG_WIFI,
+ DISALLOW_CONFIG_LOCALE,
+ DISALLOW_INSTALL_APPS,
+ DISALLOW_UNINSTALL_APPS,
+ DISALLOW_SHARE_LOCATION,
+ DISALLOW_AIRPLANE_MODE,
+ DISALLOW_CONFIG_BRIGHTNESS,
+ DISALLOW_AMBIENT_DISPLAY,
+ DISALLOW_CONFIG_SCREEN_TIMEOUT,
+ DISALLOW_INSTALL_UNKNOWN_SOURCES,
+ DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
+ DISALLOW_CONFIG_BLUETOOTH,
+ DISALLOW_BLUETOOTH,
+ DISALLOW_BLUETOOTH_SHARING,
+ DISALLOW_USB_FILE_TRANSFER,
+ DISALLOW_CONFIG_CREDENTIALS,
+ DISALLOW_REMOVE_USER,
+ DISALLOW_REMOVE_MANAGED_PROFILE,
+ DISALLOW_DEBUGGING_FEATURES,
+ DISALLOW_CONFIG_VPN,
+ DISALLOW_CONFIG_LOCATION,
+ DISALLOW_CONFIG_DATE_TIME,
+ DISALLOW_CONFIG_TETHERING,
+ DISALLOW_NETWORK_RESET,
+ DISALLOW_FACTORY_RESET,
+ DISALLOW_ADD_USER,
+ DISALLOW_ADD_MANAGED_PROFILE,
+ ENSURE_VERIFY_APPS,
+ DISALLOW_CONFIG_CELL_BROADCASTS,
+ DISALLOW_CONFIG_MOBILE_NETWORKS,
+ DISALLOW_APPS_CONTROL,
+ DISALLOW_MOUNT_PHYSICAL_MEDIA,
+ DISALLOW_UNMUTE_MICROPHONE,
+ DISALLOW_ADJUST_VOLUME,
+ DISALLOW_OUTGOING_CALLS,
+ DISALLOW_SMS,
+ DISALLOW_FUN,
+ DISALLOW_CREATE_WINDOWS,
+ DISALLOW_SYSTEM_ERROR_DIALOGS,
+ DISALLOW_CROSS_PROFILE_COPY_PASTE,
+ DISALLOW_OUTGOING_BEAM,
+ DISALLOW_WALLPAPER,
+ DISALLOW_SET_WALLPAPER,
+ DISALLOW_SAFE_BOOT,
+ DISALLOW_RECORD_AUDIO,
+ DISALLOW_RUN_IN_BACKGROUND,
+ DISALLOW_CAMERA,
+ DISALLOW_UNMUTE_DEVICE,
+ DISALLOW_DATA_ROAMING,
+ DISALLOW_SET_USER_ICON,
+ DISALLOW_OEM_UNLOCK,
+ DISALLOW_UNIFIED_PASSWORD,
+ ALLOW_PARENT_PROFILE_APP_LINKING,
+ DISALLOW_AUTOFILL,
+ DISALLOW_CONTENT_CAPTURE,
+ DISALLOW_CONTENT_SUGGESTIONS,
+ DISALLOW_USER_SWITCH,
+ DISALLOW_SHARE_INTO_MANAGED_PROFILE,
+ DISALLOW_PRINTING,
+ DISALLOW_CONFIG_PRIVATE_DNS,
+ KEY_RESTRICTIONS_PENDING,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface UserRestrictionKey {}
+
private static final String ACTION_CREATE_USER = "android.os.action.CREATE_USER";
/**
@@ -2026,7 +2103,8 @@ public class UserManager {
@SystemApi
@UserRestrictionSource
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
- public int getUserRestrictionSource(String restrictionKey, UserHandle userHandle) {
+ public int getUserRestrictionSource(@UserRestrictionKey String restrictionKey,
+ UserHandle userHandle) {
try {
return mService.getUserRestrictionSource(restrictionKey, userHandle.getIdentifier());
} catch (RemoteException re) {
@@ -2045,7 +2123,7 @@ public class UserManager {
@SystemApi
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public List<EnforcingUser> getUserRestrictionSources(
- String restrictionKey, UserHandle userHandle) {
+ @UserRestrictionKey String restrictionKey, UserHandle userHandle) {
try {
return mService.getUserRestrictionSources(restrictionKey, userHandle.getIdentifier());
} catch (RemoteException re) {
@@ -2091,7 +2169,8 @@ public class UserManager {
* @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
*/
@UnsupportedAppUsage
- public boolean hasBaseUserRestriction(String restrictionKey, UserHandle userHandle) {
+ public boolean hasBaseUserRestriction(@UserRestrictionKey String restrictionKey,
+ UserHandle userHandle) {
try {
return mService.hasBaseUserRestriction(restrictionKey, userHandle.getIdentifier());
} catch (RemoteException re) {
@@ -2162,7 +2241,7 @@ public class UserManager {
* @param restrictionKey The string key representing the restriction.
* @return {@code true} if the current user has the given restriction, {@code false} otherwise.
*/
- public boolean hasUserRestriction(String restrictionKey) {
+ public boolean hasUserRestriction(@UserRestrictionKey String restrictionKey) {
return hasUserRestrictionForUser(restrictionKey, Process.myUserHandle());
}
@@ -2174,7 +2253,8 @@ public class UserManager {
* @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
*/
@UnsupportedAppUsage
- public boolean hasUserRestriction(String restrictionKey, UserHandle userHandle) {
+ public boolean hasUserRestriction(@UserRestrictionKey String restrictionKey,
+ UserHandle userHandle) {
return hasUserRestrictionForUser(restrictionKey, userHandle);
}
@@ -2194,7 +2274,7 @@ public class UserManager {
@RequiresPermission(anyOf = {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
- public boolean hasUserRestrictionForUser(@NonNull String restrictionKey,
+ public boolean hasUserRestrictionForUser(@NonNull @UserRestrictionKey String restrictionKey,
@NonNull UserHandle userHandle) {
try {
return mService.hasUserRestriction(restrictionKey, userHandle.getIdentifier());
@@ -2207,7 +2287,7 @@ public class UserManager {
* @hide
* Returns whether any user on the device has the given user restriction set.
*/
- public boolean hasUserRestrictionOnAnyUser(String restrictionKey) {
+ public boolean hasUserRestrictionOnAnyUser(@UserRestrictionKey String restrictionKey) {
try {
return mService.hasUserRestrictionOnAnyUser(restrictionKey);
} catch (RemoteException re) {
diff --git a/core/java/android/os/connectivity/WifiActivityEnergyInfo.java b/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
index 7db003d9853c..664b6c87d339 100644
--- a/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
+++ b/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
@@ -19,9 +19,13 @@ package android.os.connectivity;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.app.ActivityThread;
+import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.os.PowerProfile;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -72,7 +76,6 @@ public final class WifiActivityEnergyInfo implements Parcelable {
* @param scanDurationMillis Cumulative milliseconds when radio is awake due to scan.
* @param idleDurationMillis Cumulative milliseconds when radio is awake but not transmitting or
* receiving.
- * @param energyUsedMicroJoules Cumulative energy consumed by Wifi, in microjoules.
*/
public WifiActivityEnergyInfo(
long timeSinceBootMillis,
@@ -80,14 +83,33 @@ public final class WifiActivityEnergyInfo implements Parcelable {
long txDurationMillis,
long rxDurationMillis,
long scanDurationMillis,
- long idleDurationMillis,
- long energyUsedMicroJoules) {
+ long idleDurationMillis) {
mTimeSinceBootMillis = timeSinceBootMillis;
mStackState = stackState;
mControllerTxDurationMillis = txDurationMillis;
mControllerRxDurationMillis = rxDurationMillis;
mControllerScanDurationMillis = scanDurationMillis;
mControllerIdleDurationMillis = idleDurationMillis;
+
+ final Context context = ActivityThread.currentActivityThread().getSystemContext();
+ if (context == null) {
+ mControllerEnergyUsedMicroJoules = 0L;
+ return;
+ }
+ // Calculate energy used using PowerProfile.
+ PowerProfile powerProfile = new PowerProfile(context);
+ final double rxIdleCurrent = powerProfile.getAveragePower(
+ PowerProfile.POWER_WIFI_CONTROLLER_IDLE);
+ final double rxCurrent = powerProfile.getAveragePower(
+ PowerProfile.POWER_WIFI_CONTROLLER_RX);
+ final double txCurrent = powerProfile.getAveragePower(
+ PowerProfile.POWER_WIFI_CONTROLLER_TX);
+ final double voltage = powerProfile.getAveragePower(
+ PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
+ final long energyUsedMicroJoules = (long) ((mControllerTxDurationMillis * txCurrent
+ + mControllerRxDurationMillis * rxCurrent
+ + mControllerIdleDurationMillis * rxIdleCurrent)
+ * voltage);
mControllerEnergyUsedMicroJoules = energyUsedMicroJoules;
}
@@ -113,9 +135,8 @@ public final class WifiActivityEnergyInfo implements Parcelable {
long rxTime = in.readLong();
long scanTime = in.readLong();
long idleTime = in.readLong();
- long energyUsed = in.readLong();
return new WifiActivityEnergyInfo(timestamp, stackState,
- txTime, rxTime, scanTime, idleTime, energyUsed);
+ txTime, rxTime, scanTime, idleTime);
}
public WifiActivityEnergyInfo[] newArray(int size) {
return new WifiActivityEnergyInfo[size];
@@ -130,7 +151,6 @@ public final class WifiActivityEnergyInfo implements Parcelable {
out.writeLong(mControllerRxDurationMillis);
out.writeLong(mControllerScanDurationMillis);
out.writeLong(mControllerIdleDurationMillis);
- out.writeLong(mControllerEnergyUsedMicroJoules);
}
@Override
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index b91d69f6dc2c..2fa3386bccb8 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -159,6 +159,8 @@ public final class MediaStore {
public static final String SCAN_FILE_CALL = "scan_file";
/** {@hide} */
public static final String SCAN_VOLUME_CALL = "scan_volume";
+ /** {@hide} */
+ public static final String SUICIDE_CALL = "suicide";
/**
* Extra used with {@link #SCAN_FILE_CALL} or {@link #SCAN_VOLUME_CALL} to indicate that
@@ -3980,6 +3982,16 @@ public final class MediaStore {
}
/** @hide */
+ public static void suicide(Context context) {
+ final ContentResolver resolver = context.getContentResolver();
+ try (ContentProviderClient client = resolver
+ .acquireUnstableContentProviderClient(AUTHORITY)) {
+ client.call(SUICIDE_CALL, null, null);
+ } catch (Exception ignored) {
+ }
+ }
+
+ /** @hide */
@TestApi
public static Uri scanFile(Context context, File file) {
return scan(context, SCAN_FILE_CALL, file, false);
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 22f90f62b114..70c8e5d311bd 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -4837,4 +4837,23 @@ public final class Telephony {
public static final Uri CONTENT_URI = Uri.parse("content://carrier_id/all");
}
}
+
+ /**
+ * Contains SIM Information
+ * @hide
+ */
+ @SystemApi
+ public static final class SimInfo {
+ /**
+ * Not instantiable.
+ * @hide
+ */
+ private SimInfo() {}
+
+ /**
+ * The {@code content://} style URI for this provider.
+ */
+ @NonNull
+ public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
+ }
}
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
index 64e15cfb7948..8cb5b05df685 100644
--- a/core/java/android/util/StatsLog.java
+++ b/core/java/android/util/StatsLog.java
@@ -179,6 +179,8 @@ public final class StatsLog extends StatsLogInternal {
* @param rollbackType state of the rollback.
* @param packageName package name being rolled back.
* @param packageVersionCode version of the package being rolled back.
+ * @param rollbackReason reason the package is being rolled back.
+ * @param failingPackageName the package name causing the failure.
*
* @return True if the log request was sent to statsd.
*
@@ -186,7 +188,7 @@ public final class StatsLog extends StatsLogInternal {
*/
@RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS})
public static boolean logWatchdogRollbackOccurred(int rollbackType, String packageName,
- long packageVersionCode) {
+ long packageVersionCode, int rollbackReason, String failingPackageName) {
synchronized (sLogLock) {
try {
IStatsManager service = getIStatsManagerLocked();
@@ -198,7 +200,7 @@ public final class StatsLog extends StatsLogInternal {
}
service.sendWatchdogRollbackOccurredAtom(rollbackType, packageName,
- packageVersionCode);
+ packageVersionCode, rollbackReason, failingPackageName);
return true;
} catch (RemoteException e) {
sService = null;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index afa661e26d4c..3171306fc568 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1646,7 +1646,7 @@ public final class ViewRootImpl implements ViewParent,
mBlastSurfaceControl, width, height);
}
- mBlastBufferQueue.update(mSurfaceControl, width, height);
+ mBlastBufferQueue.update(mBlastSurfaceControl, width, height);
mTransaction.show(mBlastSurfaceControl)
.reparent(mBlastSurfaceControl, mSurfaceControl)
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index c571737cec8f..7cec440dd80b 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -3473,18 +3473,10 @@ public class RemoteViews implements Parcelable, Filter {
return applyAsync(context, parent, executor, listener, null);
}
- private CancellationSignal startTaskOnExecutor(AsyncApplyTask task, Executor executor) {
- CancellationSignal cancelSignal = new CancellationSignal();
- cancelSignal.setOnCancelListener(task);
-
- task.executeOnExecutor(executor == null ? AsyncTask.THREAD_POOL_EXECUTOR : executor);
- return cancelSignal;
- }
-
/** @hide */
public CancellationSignal applyAsync(Context context, ViewGroup parent,
Executor executor, OnViewAppliedListener listener, OnClickHandler handler) {
- return startTaskOnExecutor(getAsyncApplyTask(context, parent, listener, handler), executor);
+ return getAsyncApplyTask(context, parent, listener, handler).startTaskOnExecutor(executor);
}
private AsyncApplyTask getAsyncApplyTask(Context context, ViewGroup parent,
@@ -3495,6 +3487,7 @@ public class RemoteViews implements Parcelable, Filter {
private class AsyncApplyTask extends AsyncTask<Void, Void, ViewTree>
implements CancellationSignal.OnCancelListener {
+ final CancellationSignal mCancelSignal = new CancellationSignal();
final RemoteViews mRV;
final ViewGroup mParent;
final Context mContext;
@@ -3545,6 +3538,7 @@ public class RemoteViews implements Parcelable, Filter {
@Override
protected void onPostExecute(ViewTree viewTree) {
+ mCancelSignal.setOnCancelListener(null);
if (mError == null) {
if (mListener != null) {
mListener.onViewInflated(viewTree.mRoot);
@@ -3581,6 +3575,13 @@ public class RemoteViews implements Parcelable, Filter {
@Override
public void onCancel() {
cancel(true);
+ mCancelSignal.setOnCancelListener(null);
+ }
+
+ private CancellationSignal startTaskOnExecutor(Executor executor) {
+ mCancelSignal.setOnCancelListener(this);
+ executeOnExecutor(executor == null ? AsyncTask.THREAD_POOL_EXECUTOR : executor);
+ return mCancelSignal;
}
}
@@ -3646,8 +3647,8 @@ public class RemoteViews implements Parcelable, Filter {
}
}
- return startTaskOnExecutor(new AsyncApplyTask(rvToApply, (ViewGroup) v.getParent(),
- context, listener, handler, v), executor);
+ return new AsyncApplyTask(rvToApply, (ViewGroup) v.getParent(),
+ context, listener, handler, v).startTaskOnExecutor(executor);
}
private void performApply(View v, ViewGroup parent, OnClickHandler handler) {
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index fd3cd42b07a1..a21187165c65 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -30,8 +30,10 @@ import android.os.SystemProperties;
import android.os.Trace;
import android.util.Log;
import android.util.Slog;
+
import com.android.internal.logging.AndroidConfig;
import com.android.server.NetworkManagementSocketTagger;
+
import dalvik.system.RuntimeHooks;
import dalvik.system.VMRuntime;
@@ -374,9 +376,6 @@ public class RuntimeInit {
// leftover running threads to crash before the process actually exits.
nativeSetExitWithoutCleanup(true);
- // We want to be fairly aggressive about heap utilization, to avoid
- // holding on to a lot of memory that isn't needed.
- VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args = new Arguments(argv);
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 897b982406dc..13cc98be5d5a 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -43,7 +43,7 @@ interface ILockSettings {
long getLong(in String key, in long defaultValue, in int userId);
@UnsupportedAppUsage
String getString(in String key, in String defaultValue, in int userId);
- boolean setLockCredential(in LockscreenCredential credential, in LockscreenCredential savedCredential, int userId, boolean allowUntrustedChange);
+ boolean setLockCredential(in LockscreenCredential credential, in LockscreenCredential savedCredential, int userId);
void resetKeyStore(int userId);
VerifyCredentialResponse checkCredential(in LockscreenCredential credential, int userId,
in ICheckCredentialProgressCallback progressCallback);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index b534213ec859..cff39f120dd7 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -636,35 +636,16 @@ public class LockPatternUtils {
*
* @param newCredential The new credential to save
* @param savedCredential The current credential
- * @param userId the user whose lockscreen credential is to be changed
- *
- * @return whether this method saved the new password successfully or not. This flow will fail
- * and return false if the given credential is wrong.
- * @throws RuntimeException if password change encountered an unrecoverable error.
- */
- public boolean setLockCredential(@NonNull LockscreenCredential newCredential,
- @NonNull LockscreenCredential savedCredential, int userId) {
- return setLockCredential(newCredential, savedCredential, userId, false);
- }
-
- /**
- * Save a new lockscreen credential.
- * <p> This method will fail (returning {@code false}) if the previously saved pattern provided
- * is incorrect and allowUntrustedChange is false, or if the lockscreen verification is still
- * being throttled.
- * @param newCredential The new credential to save
- * @param savedCredential The current credential
* @param userHandle the user whose lockscreen credential is to be changed
- * @param allowUntrustedChange whether we want to allow saving a new pattern if the existing
- * credentialt being provided is incorrect.
*
* @return whether this method saved the new password successfully or not. This flow will fail
- * and return false if the given credential is wrong and allowUntrustedChange is false.
+ * and return false if the given credential is wrong.
* @throws RuntimeException if password change encountered an unrecoverable error.
+ * @throws UnsupportedOperationException secure lockscreen is not supported on this device.
+ * @throws IllegalArgumentException if new credential is too short.
*/
public boolean setLockCredential(@NonNull LockscreenCredential newCredential,
- @NonNull LockscreenCredential savedCredential, int userHandle,
- boolean allowUntrustedChange) {
+ @NonNull LockscreenCredential savedCredential, int userHandle) {
if (!hasSecureLockScreen()) {
throw new UnsupportedOperationException(
"This operation requires the lock screen feature.");
@@ -672,8 +653,7 @@ public class LockPatternUtils {
newCredential.checkLength();
try {
- if (!getLockSettings().setLockCredential(
- newCredential, savedCredential, userHandle, allowUntrustedChange)) {
+ if (!getLockSettings().setLockCredential(newCredential, savedCredential, userHandle)) {
return false;
}
} catch (RemoteException e) {
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index dc4f09a2af6f..13bfc1bf72b8 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -66,10 +66,15 @@ import org.xmlpull.v1.XmlSerializer;
public class BootReceiver extends BroadcastReceiver {
private static final String TAG = "BootReceiver";
+ private static final String TAG_TRUNCATED = "[[TRUNCATED]]\n";
+
// Maximum size of a logged event (files get truncated if they're longer).
// Give userdebug builds a larger max to capture extra debug, esp. for last_kmsg.
private static final int LOG_SIZE =
SystemProperties.getInt("ro.debuggable", 0) == 1 ? 98304 : 65536;
+ private static final int LASTK_LOG_SIZE =
+ SystemProperties.getInt("ro.debuggable", 0) == 1 ? 196608 : 65536;
+ private static final int GMSCORE_LASTK_LOG_SIZE = 196608;
private static final File TOMBSTONE_DIR = new File("/data/tombstones");
private static final String TAG_TOMBSTONE = "SYSTEM_TOMBSTONE";
@@ -224,12 +229,12 @@ public class BootReceiver extends BroadcastReceiver {
if (db != null) db.addText("SYSTEM_BOOT", headers);
// Negative sizes mean to take the *tail* of the file (see FileUtils.readTextFile())
- addFileWithFootersToDropBox(db, timestamps, headers, lastKmsgFooter,
- "/proc/last_kmsg", -LOG_SIZE, "SYSTEM_LAST_KMSG");
- addFileWithFootersToDropBox(db, timestamps, headers, lastKmsgFooter,
- "/sys/fs/pstore/console-ramoops", -LOG_SIZE, "SYSTEM_LAST_KMSG");
- addFileWithFootersToDropBox(db, timestamps, headers, lastKmsgFooter,
- "/sys/fs/pstore/console-ramoops-0", -LOG_SIZE, "SYSTEM_LAST_KMSG");
+ addLastkToDropBox(db, timestamps, headers, lastKmsgFooter,
+ "/proc/last_kmsg", -LASTK_LOG_SIZE, "SYSTEM_LAST_KMSG");
+ addLastkToDropBox(db, timestamps, headers, lastKmsgFooter,
+ "/sys/fs/pstore/console-ramoops", -LASTK_LOG_SIZE, "SYSTEM_LAST_KMSG");
+ addLastkToDropBox(db, timestamps, headers, lastKmsgFooter,
+ "/sys/fs/pstore/console-ramoops-0", -LASTK_LOG_SIZE, "SYSTEM_LAST_KMSG");
addFileToDropBox(db, timestamps, headers, "/cache/recovery/log", -LOG_SIZE,
"SYSTEM_RECOVERY_LOG");
addFileToDropBox(db, timestamps, headers, "/cache/recovery/last_kmsg",
@@ -278,6 +283,23 @@ public class BootReceiver extends BroadcastReceiver {
sTombstoneObserver.startWatching();
}
+ private static void addLastkToDropBox(
+ DropBoxManager db, HashMap<String, Long> timestamps,
+ String headers, String footers, String filename, int maxSize,
+ String tag) throws IOException {
+ int extraSize = headers.length() + TAG_TRUNCATED.length() + footers.length();
+ // GMSCore will do 2nd truncation to be 192KiB
+ // LASTK_LOG_SIZE + extraSize must be less than GMSCORE_LASTK_LOG_SIZE
+ if (LASTK_LOG_SIZE + extraSize > GMSCORE_LASTK_LOG_SIZE) {
+ if (GMSCORE_LASTK_LOG_SIZE > extraSize) {
+ maxSize = -(GMSCORE_LASTK_LOG_SIZE - extraSize);
+ } else {
+ maxSize = 0;
+ }
+ }
+ addFileWithFootersToDropBox(db, timestamps, headers, footers, filename, maxSize, tag);
+ }
+
private static void addFileToDropBox(
DropBoxManager db, HashMap<String, Long> timestamps,
String headers, String filename, int maxSize, String tag) throws IOException {
@@ -301,7 +323,7 @@ public class BootReceiver extends BroadcastReceiver {
timestamps.put(filename, fileTime);
- String fileContents = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n");
+ String fileContents = FileUtils.readTextFile(file, maxSize, TAG_TRUNCATED);
String text = headers + fileContents + footers;
// Create an additional report for system server native crashes, with a special tag.
if (tag.equals(TAG_TOMBSTONE) && fileContents.contains(">>> system_server <<<")) {
@@ -345,7 +367,7 @@ public class BootReceiver extends BroadcastReceiver {
timestamps.put(tag, fileTime);
- String log = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n");
+ String log = FileUtils.readTextFile(file, maxSize, TAG_TRUNCATED);
StringBuilder sb = new StringBuilder();
for (String line : log.split("\n")) {
if (line.contains("audit")) {
@@ -370,7 +392,7 @@ public class BootReceiver extends BroadcastReceiver {
long fileTime = file.lastModified();
if (fileTime <= 0) return; // File does not exist
- String log = FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n");
+ String log = FileUtils.readTextFile(file, maxSize, TAG_TRUNCATED);
Pattern pattern = Pattern.compile(FS_STAT_PATTERN);
String lines[] = log.split("\n");
int lineNumber = 0;
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 378e125a3a3e..97451a2c4cfd 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -648,6 +648,7 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p
char methodTraceFileSizeBuf[sizeof("-Xmethod-trace-file-size:") + PROPERTY_VALUE_MAX];
std::string fingerprintBuf;
char jdwpProviderBuf[sizeof("-XjdwpProvider:") - 1 + PROPERTY_VALUE_MAX];
+ char opaqueJniIds[sizeof("-Xopaque-jni-ids:") - 1 + PROPERTY_VALUE_MAX];
char bootImageBuf[sizeof("-Ximage:") - 1 + PROPERTY_VALUE_MAX];
// Read if we are using the profile configuration, do this at the start since the last ART args
@@ -839,6 +840,14 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p
"default");
}
+ // Only pass an explicit opaque-jni-ids to apps forked from zygote
+ if (zygote) {
+ parseRuntimeOption("dalvik.vm.opaque-jni-ids",
+ opaqueJniIds,
+ "-Xopaque-jni-ids:",
+ "swapable");
+ }
+
parseRuntimeOption("dalvik.vm.lockprof.threshold",
lockProfThresholdBuf,
"-Xlockprofthreshold:");
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index 1ec05fb5e9fc..ecb4193a2c6c 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -264,3 +264,14 @@ message ZenPolicyProto {
optional Sender priority_calls = 16;
optional Sender priority_messages = 17;
}
+
+// Next Tag: 2
+message PackageRemoteViewInfoProto {
+ optional string package_name = 1;
+ // add per-package additional info here (like channels)
+}
+
+// Next Tag: 2
+message NotificationRemoteViewsProto {
+ repeated PackageRemoteViewInfoProto package_remote_view_info = 1;
+} \ No newline at end of file
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index cf3f51d6599a..322cbd798203 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -204,7 +204,7 @@ applications that come with the platform
<permission name="android.permission.UPDATE_DEVICE_STATS"/>
</privapp-permissions>
- <privapp-permissions package="com.android.providers.media">
+ <privapp-permissions package="com.android.providers.media.module">
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.MANAGE_USERS"/>
<permission name="android.permission.USE_RESERVED_DISK"/>
@@ -369,4 +369,7 @@ applications that come with the platform
<permission name="android.permission.REBOOT"/>
<permission name="android.permission.MANAGE_DYNAMIC_SYSTEM"/>
</privapp-permissions>
+ <privapp-permissions package="com.android.settings">
+ <permission name="android.permission.INSTALL_DYNAMIC_SYSTEM"/>
+ </privapp-permissions>
</permissions>
diff --git a/media/java/android/media/tv/tuner/FilterSettings.java b/media/java/android/media/tv/tuner/FilterSettings.java
new file mode 100644
index 000000000000..d5f100341dc6
--- /dev/null
+++ b/media/java/android/media/tv/tuner/FilterSettings.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner;
+
+import android.annotation.Nullable;
+import android.hardware.tv.tuner.V1_0.Constants;
+import android.media.tv.tuner.TunerConstants.FilterSettingsType;
+
+import java.util.List;
+
+/**
+ * Demux Filter settings.
+ *
+ * @hide
+ */
+public abstract class FilterSettings {
+ @Nullable
+ protected final Settings mSettings;
+
+ protected FilterSettings(Settings settings) {
+ mSettings = settings;
+ }
+
+ /**
+ * Gets filter settings type
+ */
+ @FilterSettingsType public abstract int getType();
+
+ // TODO: more builders and getters
+
+ /**
+ * Filter Settings for a TS filter.
+ */
+ public static class TsFilterSettings extends FilterSettings {
+ private int mTpid;
+
+ private TsFilterSettings(Settings settings, int tpid) {
+ super(settings);
+ mTpid = tpid;
+ }
+
+ @Override
+ public int getType() {
+ return TunerConstants.FILTER_SETTINGS_TS;
+ }
+
+ /**
+ * Creates a new builder.
+ */
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder for TsFilterSettings.
+ */
+ public static class Builder {
+ private Settings mSettings;
+ private int mTpid;
+
+ /**
+ * Sets settings.
+ */
+ public Builder setSettings(Settings settings) {
+ mSettings = settings;
+ return this;
+ }
+
+ /**
+ * Sets TPID.
+ */
+ public Builder setTpid(int tpid) {
+ mTpid = tpid;
+ return this;
+ }
+
+ /**
+ * Builds a TsFilterSettings instance.
+ */
+ public TsFilterSettings build() {
+ return new TsFilterSettings(mSettings, mTpid);
+ }
+ }
+ }
+
+ /**
+ * Filter Settings for a MMTP filter.
+ */
+ public static class MmtpFilterSettings extends FilterSettings {
+ private int mMmtpPid;
+
+ public MmtpFilterSettings(Settings settings) {
+ super(settings);
+ }
+
+ @Override
+ public int getType() {
+ return TunerConstants.FILTER_SETTINGS_MMTP;
+ }
+ }
+
+
+ /**
+ * Filter Settings for a IP filter.
+ */
+ public static class IpFilterSettings extends FilterSettings {
+ private byte[] mSrcIpAddress;
+ private byte[] mDstIpAddress;
+ private int mSrcPort;
+ private int mDstPort;
+ private boolean mPassthrough;
+
+ public IpFilterSettings(Settings settings) {
+ super(settings);
+ }
+
+ @Override
+ public int getType() {
+ return TunerConstants.FILTER_SETTINGS_IP;
+ }
+ }
+
+
+ /**
+ * Filter Settings for a TLV filter.
+ */
+ public static class TlvFilterSettings extends FilterSettings {
+ private int mPacketType;
+ private boolean mIsCompressedIpPacket;
+ private boolean mPassthrough;
+
+ public TlvFilterSettings(Settings settings) {
+ super(settings);
+ }
+
+ @Override
+ public int getType() {
+ return TunerConstants.FILTER_SETTINGS_TLV;
+ }
+ }
+
+
+ /**
+ * Filter Settings for a ALP filter.
+ */
+ public static class AlpFilterSettings extends FilterSettings {
+ private int mPacketType;
+ private int mLengthType;
+
+ public AlpFilterSettings(Settings settings) {
+ super(settings);
+ }
+
+ @Override
+ public int getType() {
+ return TunerConstants.FILTER_SETTINGS_ALP;
+ }
+ }
+
+
+ /**
+ * Settings for filters of different subtypes.
+ */
+ public abstract static class Settings {
+ protected final int mType;
+
+ protected Settings(int type) {
+ mType = type;
+ }
+
+ /**
+ * Gets filter settings type.
+ * @return
+ */
+ int getType() {
+ return mType;
+ }
+ }
+
+ /**
+ * Filter Settings for Section data according to ISO/IEC 13818-1.
+ */
+ public static class SectionSettings extends Settings {
+
+ private SectionSettings(int mainType) {
+ super(SectionSettings.findType(mainType));
+ }
+
+ private static int findType(int mainType) {
+ switch (mainType) {
+ case TunerConstants.FILTER_SETTINGS_TS:
+ return Constants.DemuxTsFilterType.SECTION;
+ case TunerConstants.FILTER_SETTINGS_MMTP:
+ return Constants.DemuxMmtpFilterType.SECTION;
+ case TunerConstants.FILTER_SETTINGS_IP:
+ return Constants.DemuxIpFilterType.SECTION;
+ case TunerConstants.FILTER_SETTINGS_TLV:
+ return Constants.DemuxTlvFilterType.SECTION;
+ case TunerConstants.FILTER_SETTINGS_ALP:
+ return Constants.DemuxAlpFilterType.SECTION;
+ }
+ // UNDEFINED
+ return 0;
+ }
+ }
+
+ /**
+ * Bits Settings for Section Filter.
+ */
+ public static class SectionSettingsWithSectionBits extends SectionSettings {
+ private List<Byte> mFilter;
+ private List<Byte> mMask;
+ private List<Byte> mMode;
+
+ private SectionSettingsWithSectionBits(int mainType) {
+ super(mainType);
+ }
+ }
+
+ /**
+ * Table information for Section Filter.
+ */
+ public static class SectionSettingsWithTableInfo extends SectionSettings {
+ private int mTableId;
+ private int mVersion;
+
+ private SectionSettingsWithTableInfo(int mainType) {
+ super(mainType);
+ }
+ }
+
+ /**
+ * Filter Settings for a PES Data.
+ */
+ public static class PesSettings extends Settings {
+ private int mStreamId;
+ private boolean mIsRaw;
+
+ private PesSettings(int mainType, int streamId, boolean isRaw) {
+ super(PesSettings.findType(mainType));
+ mStreamId = streamId;
+ mIsRaw = isRaw;
+ }
+
+ private static int findType(int mainType) {
+ switch (mainType) {
+ case TunerConstants.FILTER_SETTINGS_TS:
+ return Constants.DemuxTsFilterType.PES;
+ case TunerConstants.FILTER_SETTINGS_MMTP:
+ return Constants.DemuxMmtpFilterType.PES;
+ }
+ // UNDEFINED
+ return 0;
+ }
+
+ /**
+ * Creates a builder for PesSettings.
+ */
+ public static Builder newBuilder(int mainType) {
+ return new Builder(mainType);
+ }
+
+ /**
+ * Builder for PesSettings.
+ */
+ public static class Builder {
+ private final int mMainType;
+ private int mStreamId;
+ private boolean mIsRaw;
+
+ public Builder(int mainType) {
+ mMainType = mainType;
+ }
+
+ /**
+ * Sets stream ID.
+ */
+ public Builder setStreamId(int streamId) {
+ mStreamId = streamId;
+ return this;
+ }
+
+ /**
+ * Sets whether it's raw.
+ * true if the filter send onFilterStatus instead of onFilterEvent.
+ */
+ public Builder setIsRaw(boolean isRaw) {
+ mIsRaw = isRaw;
+ return this;
+ }
+
+ /**
+ * Builds a PesSettings instance.
+ */
+ public PesSettings build() {
+ return new PesSettings(mMainType, mStreamId, mIsRaw);
+ }
+ }
+ }
+
+ /**
+ * Filter Settings for a Video and Audio.
+ */
+ public static class AvSettings extends Settings {
+ private boolean mIsPassthrough;
+
+ private AvSettings(int mainType, boolean isAudio) {
+ super(AvSettings.findType(mainType, isAudio));
+ }
+
+ private static int findType(int mainType, boolean isAudio) {
+ switch (mainType) {
+ case TunerConstants.FILTER_SETTINGS_TS:
+ return isAudio
+ ? Constants.DemuxTsFilterType.AUDIO
+ : Constants.DemuxTsFilterType.VIDEO;
+ case TunerConstants.FILTER_SETTINGS_MMTP:
+ return isAudio
+ ? Constants.DemuxMmtpFilterType.AUDIO
+ : Constants.DemuxMmtpFilterType.VIDEO;
+ }
+ // UNDEFINED
+ return 0;
+ }
+ }
+
+ /**
+ * Filter Settings for a Download.
+ */
+ public static class DownloadSettings extends Settings {
+ private int mDownloadId;
+
+ public DownloadSettings(int mainType) {
+ super(DownloadSettings.findType(mainType));
+ }
+
+ private static int findType(int mainType) {
+ if (mainType == TunerConstants.FILTER_SETTINGS_MMTP) {
+ return Constants.DemuxMmtpFilterType.DOWNLOAD;
+ }
+ // UNDEFINED
+ return 0;
+ }
+ }
+
+ /**
+ * The Settings for the record in DVR.
+ */
+ public static class RecordSettings extends Settings {
+ private int mIndexType;
+ private int mIndexMask;
+
+ public RecordSettings(int mainType) {
+ super(RecordSettings.findType(mainType));
+ }
+
+ private static int findType(int mainType) {
+ switch (mainType) {
+ case TunerConstants.FILTER_SETTINGS_TS:
+ return Constants.DemuxTsFilterType.RECORD;
+ case TunerConstants.FILTER_SETTINGS_MMTP:
+ return Constants.DemuxMmtpFilterType.RECORD;
+ }
+ // UNDEFINED
+ return 0;
+ }
+ }
+
+}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 82cef2e43307..6537f6fb5a2b 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -243,9 +243,11 @@ public final class Tuner implements AutoCloseable {
private FilterCallback mCallback;
int mId;
+ private native int nativeConfigureFilter(int type, int subType, FilterSettings settings);
private native boolean nativeStartFilter();
private native boolean nativeStopFilter();
private native boolean nativeFlushFilter();
+ private native int nativeRead(byte[] buffer, int offset, int size);
private Filter(int id) {
mId = id;
@@ -258,6 +260,14 @@ public final class Tuner implements AutoCloseable {
}
}
+ public int configure(FilterSettings settings) {
+ int subType = -1;
+ if (settings.mSettings != null) {
+ subType = settings.mSettings.getType();
+ }
+ return nativeConfigureFilter(settings.getType(), subType, settings);
+ }
+
public boolean start() {
return nativeStartFilter();
}
@@ -269,6 +279,11 @@ public final class Tuner implements AutoCloseable {
public boolean flush() {
return nativeFlushFilter();
}
+
+ public int read(@NonNull byte[] buffer, int offset, int size) {
+ size = Math.min(size, buffer.length - offset);
+ return nativeRead(buffer, offset, size);
+ }
}
private Filter openFilter(int type, int subType, int bufferSize, FilterCallback cb) {
diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java
index 458cb1678ded..f2d5e939f532 100644
--- a/media/java/android/media/tv/tuner/TunerConstants.java
+++ b/media/java/android/media/tv/tuner/TunerConstants.java
@@ -90,6 +90,17 @@ final class TunerConstants {
public static final int FRONTEND_SETTINGS_ISDBS3 = 8;
public static final int FRONTEND_SETTINGS_ISDBT = 9;
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({FILTER_SETTINGS_TS, FILTER_SETTINGS_MMTP, FILTER_SETTINGS_IP, FILTER_SETTINGS_TLV,
+ FILTER_SETTINGS_ALP})
+ public @interface FilterSettingsType {}
+
+ public static final int FILTER_SETTINGS_TS = Constants.DemuxFilterMainType.TS;
+ public static final int FILTER_SETTINGS_MMTP = Constants.DemuxFilterMainType.MMTP;
+ public static final int FILTER_SETTINGS_IP = Constants.DemuxFilterMainType.IP;
+ public static final int FILTER_SETTINGS_TLV = Constants.DemuxFilterMainType.TLV;
+ public static final int FILTER_SETTINGS_ALP = Constants.DemuxFilterMainType.ALP;
+
private TunerConstants() {
}
}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 12b3e6735d81..4ca23a1084a2 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -135,6 +135,8 @@ cc_library_shared {
shared_libs: [
"android.hardware.tv.tuner@1.0",
"libandroid_runtime",
+ "libcutils",
+ "libfmq",
"libhidlbase",
"liblog",
"libutils",
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 5216906d5ec5..a0be12ebecfc 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -28,8 +28,12 @@
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxMmtpPid;
+using ::android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
using ::android::hardware::tv::tuner::V1_0::DemuxTpid;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSettings;
using ::android::hardware::tv::tuner::V1_0::FrontendAnalogSifStandard;
@@ -112,6 +116,26 @@ void FilterCallback::setFilter(const jobject filter) {
mFilter = env->NewWeakGlobalRef(filter);
}
+/////////////// Filter ///////////////////////
+
+Filter::Filter(sp<IFilter> sp, jweak obj) : mFilterSp(sp), mFilterObj(obj) {}
+
+Filter::~Filter() {
+ EventFlag::deleteEventFlag(&mFilterMQEventFlag);
+}
+
+int Filter::close() {
+ Result r = mFilterSp->close();
+ if (r == Result::SUCCESS) {
+ EventFlag::deleteEventFlag(&mFilterMQEventFlag);
+ }
+ return (int)r;
+}
+
+sp<IFilter> Filter::getIFilter() {
+ return mFilterSp;
+}
+
/////////////// FrontendCallback ///////////////////////
FrontendCallback::FrontendCallback(jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {}
@@ -211,6 +235,7 @@ jobject JTuner::openFrontendById(int id) {
fe->setCallback(feCb);
jint jId = (jint) id;
+
JNIEnv *env = AndroidRuntime::getJNIEnv();
// TODO: add more fields to frontend
return env->NewObject(
@@ -327,18 +352,18 @@ jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
}
}
- sp<IFilter> filterSp;
+ sp<IFilter> iFilterSp;
sp<FilterCallback> callback = new FilterCallback();
mDemux->openFilter(type, bufferSize, callback,
[&](Result, const sp<IFilter>& filter) {
- filterSp = filter;
+ iFilterSp = filter;
});
- if (filterSp == NULL) {
+ if (iFilterSp == NULL) {
ALOGD("Failed to open filter, type = %d", type.mainType);
return NULL;
}
int fId;
- filterSp->getId([&](Result, uint32_t filterId) {
+ iFilterSp->getId([&](Result, uint32_t filterId) {
fId = filterId;
});
@@ -350,6 +375,7 @@ jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
mObject,
(jint) fId);
+ sp<Filter> filterSp = new Filter(iFilterSp, filterObj);
filterSp->incStrong(filterObj);
env->SetLongField(filterObj, gFields.filterContext, (jlong)filterSp.get());
@@ -432,7 +458,7 @@ static DemuxPid getDemuxPid(int pidType, int pid) {
static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject settings) {
FrontendSettings frontendSettings;
jclass clazz = env->FindClass("android/media/tv/tuner/FrontendSettings");
- jfieldID freqField = env->GetFieldID(clazz, "frequency", "I");
+ jfieldID freqField = env->GetFieldID(clazz, "mFrequency", "I");
uint32_t freq = static_cast<uint32_t>(env->GetIntField(clazz, freqField));
// TODO: handle the other 8 types of settings
@@ -455,8 +481,8 @@ static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject setti
return frontendSettings;
}
-static sp<IFilter> getFilter(JNIEnv *env, jobject filter) {
- return (IFilter *)env->GetLongField(filter, gFields.filterContext);
+static sp<Filter> getFilter(JNIEnv *env, jobject filter) {
+ return (Filter *)env->GetLongField(filter, gFields.filterContext);
}
static sp<IDvr> getDvr(JNIEnv *env, jobject dvr) {
@@ -542,8 +568,100 @@ static jobject android_media_tv_Tuner_open_filter(
return tuner->openFilter(filterType, bufferSize);
}
+static DemuxFilterSettings getFilterSettings(
+ JNIEnv *env, int type, int subtype, jobject filterSettingsObj) {
+ DemuxFilterSettings filterSettings;
+ // TODO: more setting types
+ jobject settingsObj =
+ env->GetObjectField(
+ filterSettingsObj,
+ env->GetFieldID(
+ env->FindClass("android/media/tv/tuner/FilterSettings"),
+ "mSettings",
+ "Landroid/media/tv/tuner/FilterSettings$Settings;"));
+ if (type == (int)DemuxFilterMainType::TS) {
+ // DemuxTsFilterSettings
+ jclass clazz = env->FindClass("android/media/tv/tuner/FilterSettings$TsFilterSettings");
+ int tpid = env->GetIntField(filterSettingsObj, env->GetFieldID(clazz, "mTpid", "I"));
+ if (subtype == (int)DemuxTsFilterType::PES) {
+ // DemuxFilterPesDataSettings
+ jclass settingClazz =
+ env->FindClass("android/media/tv/tuner/FilterSettings$PesSettings");
+ int streamId = env->GetIntField(
+ settingsObj, env->GetFieldID(settingClazz, "mStreamId", "I"));
+ bool isRaw = (bool)env->GetBooleanField(
+ settingsObj, env->GetFieldID(settingClazz, "mIsRaw", "Z"));
+ DemuxFilterPesDataSettings filterPesDataSettings {
+ .streamId = static_cast<uint16_t>(streamId),
+ .isRaw = isRaw,
+ };
+ DemuxTsFilterSettings tsFilterSettings {
+ .tpid = static_cast<uint16_t>(tpid),
+ };
+ tsFilterSettings.filterSettings.pesData(filterPesDataSettings);
+ filterSettings.ts(tsFilterSettings);
+ }
+ }
+ return filterSettings;
+}
+
+static int copyData(JNIEnv *env, sp<Filter> filter, jbyteArray buffer, jint offset, int size) {
+ ALOGD("copyData, size=%d, offset=%d", size, offset);
+
+ int available = filter->mFilterMQ->availableToRead();
+ ALOGD("copyData, available=%d", available);
+ size = std::min(size, available);
+
+ jboolean isCopy;
+ jbyte *dst = env->GetByteArrayElements(buffer, &isCopy);
+ ALOGD("copyData, isCopy=%d", isCopy);
+ if (dst == nullptr) {
+ ALOGD("Failed to GetByteArrayElements");
+ return 0;
+ }
+
+ if (filter->mFilterMQ->read(reinterpret_cast<unsigned char*>(dst) + offset, size)) {
+ env->ReleaseByteArrayElements(buffer, dst, 0);
+ filter->mFilterMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
+ } else {
+ ALOGD("Failed to read FMQ");
+ env->ReleaseByteArrayElements(buffer, dst, 0);
+ return 0;
+ }
+ return size;
+}
+
+static int android_media_tv_Tuner_configure_filter(
+ JNIEnv *env, jobject filter, int type, int subtype, jobject settings) {
+ ALOGD("configure filter type=%d, subtype=%d", type, subtype);
+ sp<Filter> filterSp = getFilter(env, filter);
+ sp<IFilter> iFilterSp = filterSp->getIFilter();
+ if (iFilterSp == NULL) {
+ ALOGD("Failed to configure filter: filter not found");
+ return (int)Result::INVALID_STATE;
+ }
+ DemuxFilterSettings filterSettings = getFilterSettings(env, type, subtype, settings);
+ Result res = iFilterSp->configure(filterSettings);
+ MQDescriptorSync<uint8_t> filterMQDesc;
+ if (res == Result::SUCCESS && filterSp->mFilterMQ == NULL) {
+ Result getQueueDescResult = Result::UNKNOWN_ERROR;
+ iFilterSp->getQueueDesc(
+ [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
+ filterMQDesc = desc;
+ getQueueDescResult = r;
+ ALOGD("getFilterQueueDesc");
+ });
+ if (getQueueDescResult == Result::SUCCESS) {
+ filterSp->mFilterMQ = std::make_unique<FilterMQ>(filterMQDesc, true);
+ EventFlag::createEventFlag(
+ filterSp->mFilterMQ->getEventFlagWord(), &(filterSp->mFilterMQEventFlag));
+ }
+ }
+ return (int)res;
+}
+
static bool android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) {
- sp<IFilter> filterSp = getFilter(env, filter);
+ sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
if (filterSp == NULL) {
ALOGD("Failed to start filter: filter not found");
return false;
@@ -552,7 +670,7 @@ static bool android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) {
}
static bool android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) {
- sp<IFilter> filterSp = getFilter(env, filter);
+ sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
if (filterSp == NULL) {
ALOGD("Failed to stop filter: filter not found");
return false;
@@ -561,7 +679,7 @@ static bool android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) {
}
static bool android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) {
- sp<IFilter> filterSp = getFilter(env, filter);
+ sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
if (filterSp == NULL) {
ALOGD("Failed to flush filter: filter not found");
return false;
@@ -569,6 +687,16 @@ static bool android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) {
return filterSp->flush() == Result::SUCCESS;
}
+static int android_media_tv_Tuner_read_filter_fmq(
+ JNIEnv *env, jobject filter, jbyteArray buffer, jint offset, jint size) {
+ sp<Filter> filterSp = getFilter(env, filter);
+ if (filterSp == NULL) {
+ ALOGD("Failed to read filter FMQ: filter not found");
+ return 0;
+ }
+ return copyData(env, filterSp, buffer, offset, size);
+}
+
static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz) {
sp<JTuner> tuner = getTuner(env, thiz);
return tuner->openDescrambler();
@@ -580,7 +708,7 @@ static bool android_media_tv_Tuner_add_pid(
if (descramblerSp == NULL) {
return false;
}
- sp<IFilter> filterSp = getFilter(env, filter);
+ sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
Result result = descramblerSp->addPid(getDemuxPid((int)pidType, (int)pid), filterSp);
return result == Result::SUCCESS;
}
@@ -591,7 +719,7 @@ static bool android_media_tv_Tuner_remove_pid(
if (descramblerSp == NULL) {
return false;
}
- sp<IFilter> filterSp = getFilter(env, filter);
+ sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
Result result = descramblerSp->removePid(getDemuxPid((int)pidType, (int)pid), filterSp);
return result == Result::SUCCESS;
}
@@ -603,7 +731,7 @@ static jobject android_media_tv_Tuner_open_dvr(JNIEnv *env, jobject thiz, jint t
static bool android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobject filter) {
sp<IDvr> dvrSp = getDvr(env, dvr);
- sp<IFilter> filterSp = getFilter(env, filter);
+ sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
if (dvrSp == NULL || filterSp == NULL) {
return false;
}
@@ -613,7 +741,7 @@ static bool android_media_tv_Tuner_attach_filter(JNIEnv *env, jobject dvr, jobje
static bool android_media_tv_Tuner_detach_filter(JNIEnv *env, jobject dvr, jobject filter) {
sp<IDvr> dvrSp = getDvr(env, dvr);
- sp<IFilter> filterSp = getFilter(env, filter);
+ sp<IFilter> filterSp = getFilter(env, filter)->getIFilter();
if (dvrSp == NULL || filterSp == NULL) {
return false;
}
@@ -670,9 +798,12 @@ static const JNINativeMethod gTunerMethods[] = {
};
static const JNINativeMethod gFilterMethods[] = {
+ { "nativeConfigureFilter", "(IILandroid/media/tv/tuner/FilterSettings;)I",
+ (void *)android_media_tv_Tuner_configure_filter },
{ "nativeStartFilter", "()Z", (void *)android_media_tv_Tuner_start_filter },
{ "nativeStopFilter", "()Z", (void *)android_media_tv_Tuner_stop_filter },
{ "nativeFlushFilter", "()Z", (void *)android_media_tv_Tuner_flush_filter },
+ { "nativeRead", "([BII)I", (void *)android_media_tv_Tuner_read_filter_fmq },
};
static const JNINativeMethod gDescramblerMethods[] = {
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index f856791e2618..467acb8cdbdd 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -18,13 +18,18 @@
#define _ANDROID_MEDIA_TV_TUNER_H_
#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <fmq/MessageQueue.h>
#include <unordered_map>
#include <utils/RefBase.h>
#include "jni.h"
+using ::android::hardware::EventFlag;
+using ::android::hardware::MQDescriptorSync;
+using ::android::hardware::MessageQueue;
using ::android::hardware::Return;
using ::android::hardware::hidl_vec;
+using ::android::hardware::kSynchronizedReadWrite;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
@@ -51,6 +56,8 @@ using ::android::hardware::tv::tuner::V1_0::LnbId;
using ::android::hardware::tv::tuner::V1_0::PlaybackStatus;
using ::android::hardware::tv::tuner::V1_0::RecordStatus;
+using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
namespace android {
struct LnbCallback : public ILnbCallback {
@@ -91,6 +98,17 @@ struct FrontendCallback : public IFrontendCallback {
FrontendId mId;
};
+struct Filter : public RefBase {
+ Filter(sp<IFilter> sp, jweak obj);
+ ~Filter();
+ int close();
+ sp<IFilter> getIFilter();
+ sp<IFilter> mFilterSp;
+ std::unique_ptr<FilterMQ> mFilterMQ;
+ EventFlag* mFilterMQEventFlag;
+ jweak mFilterObj;
+};
+
struct JTuner : public RefBase {
JTuner(JNIEnv *env, jobject thiz);
sp<ITuner> getTunerService();
diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp
index 79e4d8ae6e26..c8f0ff10ca3f 100644
--- a/media/jni/soundpool/StreamManager.cpp
+++ b/media/jni/soundpool/StreamManager.cpp
@@ -38,7 +38,7 @@ static constexpr bool kStealActiveStream_OldestFirst = true;
// kPlayOnCallingThread = true prior to R.
// Changing to false means calls to play() are almost instantaneous instead of taking around
// ~10ms to launch the AudioTrack. It is perhaps 100x faster.
-static constexpr bool kPlayOnCallingThread = true;
+static constexpr bool kPlayOnCallingThread = false;
// Amount of time for a StreamManager thread to wait before closing.
static constexpr int64_t kWaitTimeBeforeCloseNs = 9 * NANOS_PER_SECOND;
@@ -170,7 +170,6 @@ int32_t StreamManager::queueForPlay(const std::shared_ptr<Sound> &sound,
if (stream->getSoundID() == soundID) {
ALOGV("%s: found soundID %d in restart queue", __func__, soundID);
newStream = stream;
- fromAvailableQueue = false;
break;
} else if (newStream == nullptr) {
ALOGV("%s: found stream in restart queue", __func__);
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 45430197fdd8..291cdd5ea3d8 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -35,6 +35,7 @@ import android.view.ViewStub;
import androidx.recyclerview.widget.GridLayoutManager;
+import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.R;
import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.dagger.qualifiers.MainResources;
@@ -135,8 +136,9 @@ public class FullscreenUserSwitcher {
/* isAddUser= */ false,
/* isForeground= */ true);
- // If the initial user has trusted device, display the unlock dialog on the keyguard.
- if (hasTrustedDevice(initialUser)) {
+ // If the initial user has screen lock and trusted device, display the unlock dialog on the
+ // keyguard.
+ if (hasScreenLock(initialUser) && hasTrustedDevice(initialUser)) {
mUnlockDialogHelper.showUnlockDialogAfterDelay(initialUser,
mOnHideListener);
} else {
@@ -178,7 +180,7 @@ public class FullscreenUserSwitcher {
*/
private void onUserSelected(UserGridRecyclerView.UserRecord record) {
mSelectedUser = record;
- if (hasTrustedDevice(record.mInfo.id)) {
+ if (hasScreenLock(record.mInfo.id) && hasTrustedDevice(record.mInfo.id)) {
mUnlockDialogHelper.showUnlockDialog(record.mInfo.id, mOnHideListener);
return;
}
@@ -216,6 +218,12 @@ public class FullscreenUserSwitcher {
}
+ private boolean hasScreenLock(int uid) {
+ LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
+ return lockPatternUtils.getCredentialTypeForUser(uid)
+ != LockPatternUtils.CREDENTIAL_TYPE_NONE;
+ }
+
private boolean hasTrustedDevice(int uid) {
if (mEnrollmentManager == null) { // car service not ready, so it cannot be available.
return false;
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index 26ec5726a4a2..9f13a7b861a0 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -9,12 +9,6 @@
"include-filter": "android.platform.test.scenario.sysui"
},
{
- "include-filter": "android.platform.test.scenario.quicksettings"
- },
- {
- "include-filter": "android.platform.test.scenario.notification"
- },
- {
"include-annotation": "android.platform.test.scenario.annotation.Scenario"
},
{
diff --git a/packages/SystemUI/res/layout/bubble_menu_view.xml b/packages/SystemUI/res/layout/bubble_menu_view.xml
new file mode 100644
index 000000000000..24608d3e9611
--- /dev/null
+++ b/packages/SystemUI/res/layout/bubble_menu_view.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<com.android.systemui.bubbles.BubbleMenuView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:background="#66000000"
+ android:visibility="gone"
+ android:id="@+id/bubble_menu_container">
+
+ <FrameLayout
+ android:layout_height="@dimen/individual_bubble_size"
+ android:layout_width="wrap_content"
+ android:background="#FFFFFF"
+ android:id="@+id/bubble_menu_view">
+
+ <ImageView
+ android:id="@*android:id/icon"
+ android:layout_width="@dimen/global_actions_grid_item_icon_width"
+ android:layout_height="@dimen/global_actions_grid_item_icon_height"
+ android:layout_marginTop="@dimen/global_actions_grid_item_icon_top_margin"
+ android:layout_marginBottom="@dimen/global_actions_grid_item_icon_bottom_margin"
+ android:layout_marginLeft="@dimen/global_actions_grid_item_icon_side_margin"
+ android:layout_marginRight="@dimen/global_actions_grid_item_icon_side_margin"
+ android:scaleType="centerInside"
+ android:tint="@color/global_actions_text"
+ />
+ </FrameLayout>
+</com.android.systemui.bubbles.BubbleMenuView>
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
new file mode 100644
index 000000000000..27db294a98d8
--- /dev/null
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources>
+ <!-- SystemUI Services: The classes of the stuff to start. -->
+ <string-array name="config_systemUIServiceComponents" translatable="false">
+ <item>com.android.systemui.volume.VolumeUI</item>
+ <item>com.android.systemui.stackdivider.Divider</item>
+ <item>com.android.systemui.statusbar.tv.TvStatusBar</item>
+ <item>com.android.systemui.usb.StorageNotification</item>
+ <item>com.android.systemui.power.PowerUI</item>
+ <item>com.android.systemui.media.RingtonePlayer</item>
+ <item>com.android.systemui.keyboard.KeyboardUI</item>
+ <item>com.android.systemui.pip.PipUI</item>
+ <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
+ <item>@string/config_systemUIVendorServiceComponent</item>
+ <item>com.android.systemui.SliceBroadcastRelayHandler</item>
+ <item>com.android.systemui.SizeCompatModeActivityController</item>
+ <item>com.android.systemui.statusbar.notification.InstantAppNotifier</item>
+ </string-array>
+</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index dbb193669083..19381940543e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -44,13 +44,19 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.UserIdInt;
import android.app.ActivityManager.RunningTaskInfo;
+import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.app.RemoteInput;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ShortcutManager;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.service.notification.NotificationListenerService.RankingMap;
@@ -69,6 +75,7 @@ import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.util.ScreenshotHelper;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -86,6 +93,7 @@ import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.ZenModeController;
import java.io.FileDescriptor;
@@ -93,8 +101,10 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.function.Consumer;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -138,6 +148,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
@Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer;
private final NotificationGroupManager mNotificationGroupManager;
private final Lazy<ShadeController> mShadeController;
+ private final RemoteInputUriController mRemoteInputUriController;
+ private Handler mHandler = new Handler() {};
private BubbleData mBubbleData;
@Nullable private BubbleStackView mStackView;
@@ -155,6 +167,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
private final StatusBarWindowController mStatusBarWindowController;
private final ZenModeController mZenModeController;
private StatusBarStateListener mStatusBarStateListener;
+ private final ScreenshotHelper mScreenshotHelper;
+
private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
private IStatusBarService mBarService;
@@ -192,6 +206,16 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
}
/**
+ * Listener for handling bubble screenshot events.
+ */
+ public interface BubbleScreenshotListener {
+ /**
+ * Called to trigger taking a screenshot and sending the result to a bubble.
+ */
+ void onBubbleScreenshot(Bubble bubble);
+ }
+
+ /**
* Listens for the current state of the status bar and updates the visibility state
* of bubbles as needed.
*/
@@ -226,10 +250,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
ZenModeController zenModeController,
NotificationLockscreenUserManager notifUserManager,
NotificationGroupManager groupManager,
- NotificationEntryManager entryManager) {
+ NotificationEntryManager entryManager,
+ RemoteInputUriController remoteInputUriController) {
this(context, statusBarWindowController, statusBarStateController, shadeController,
data, null /* synchronizer */, configurationController, interruptionStateProvider,
- zenModeController, notifUserManager, groupManager, entryManager);
+ zenModeController, notifUserManager, groupManager, entryManager,
+ remoteInputUriController);
}
public BubbleController(Context context,
@@ -243,11 +269,13 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
ZenModeController zenModeController,
NotificationLockscreenUserManager notifUserManager,
NotificationGroupManager groupManager,
- NotificationEntryManager entryManager) {
+ NotificationEntryManager entryManager,
+ RemoteInputUriController remoteInputUriController) {
mContext = context;
mNotificationInterruptionStateProvider = interruptionStateProvider;
mNotifUserManager = notifUserManager;
mZenModeController = zenModeController;
+ mRemoteInputUriController = remoteInputUriController;
mZenModeController.addCallback(new ZenModeController.Callback() {
@Override
public void onZenChanged(int zen) {
@@ -320,6 +348,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
});
mUserCreatedBubbles = new HashSet<>();
+
+ mScreenshotHelper = new ScreenshotHelper(context);
}
/**
@@ -337,6 +367,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
if (mExpandListener != null) {
mStackView.setExpandListener(mExpandListener);
}
+ if (mBubbleScreenshotListener != null) {
+ mStackView.setBubbleScreenshotListener(mBubbleScreenshotListener);
+ }
}
}
@@ -1058,4 +1091,71 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
}
}
}
+
+ // TODO: Copied from RemoteInputView. Consolidate RemoteInput intent logic.
+ private Intent prepareRemoteInputFromData(String contentType, Uri data,
+ RemoteInput remoteInput, NotificationEntry entry) {
+ HashMap<String, Uri> results = new HashMap<>();
+ results.put(contentType, data);
+ mRemoteInputUriController.grantInlineReplyUriPermission(entry.getSbn(), data);
+ Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ RemoteInput.addDataResultToIntent(remoteInput, fillInIntent, results);
+
+ return fillInIntent;
+ }
+
+ // TODO: Copied from RemoteInputView. Consolidate RemoteInput intent logic.
+ private void sendRemoteInput(Intent intent, NotificationEntry entry,
+ PendingIntent pendingIntent) {
+ // Tell ShortcutManager that this package has been "activated". ShortcutManager
+ // will reset the throttling for this package.
+ // Strictly speaking, the intent receiver may be different from the notification publisher,
+ // but that's an edge case, and also because we can't always know which package will receive
+ // an intent, so we just reset for the publisher.
+ mContext.getSystemService(ShortcutManager.class).onApplicationActive(
+ entry.getSbn().getPackageName(),
+ entry.getSbn().getUser().getIdentifier());
+
+ try {
+ pendingIntent.send(mContext, 0, intent);
+ } catch (PendingIntent.CanceledException e) {
+ Log.i(TAG, "Unable to send remote input result", e);
+ }
+ }
+
+ private void sendScreenshotToBubble(Bubble bubble) {
+ // delay allows the bubble menu to disappear before the screenshot
+ // done here because we already have a Handler to delay with.
+ // TODO: Hide bubble + menu UI from screenshots entirely instead of just delaying.
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mScreenshotHelper.takeScreenshot(
+ android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN,
+ true /* hasStatus */,
+ true /* hasNav */,
+ mHandler,
+ new Consumer<Uri>() {
+ @Override
+ public void accept(Uri uri) {
+ if (uri != null) {
+ NotificationEntry entry = bubble.getEntry();
+ Pair<RemoteInput, Notification.Action> pair = entry.getSbn()
+ .getNotification().findRemoteInputActionPair(false);
+ RemoteInput remoteInput = pair.first;
+ Notification.Action action = pair.second;
+ Intent dataIntent = prepareRemoteInputFromData("image/png", uri,
+ remoteInput, entry);
+ sendRemoteInput(dataIntent, entry, action.actionIntent);
+ mBubbleData.setSelectedBubble(bubble);
+ mBubbleData.setExpanded(true);
+ }
+ }
+ });
+ }
+ }, 200);
+ }
+
+ private final BubbleScreenshotListener mBubbleScreenshotListener =
+ bubble -> sendScreenshotToBubble(bubble);
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java
index e138d9387ca6..8299f2261b8e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExperimentConfig.java
@@ -68,6 +68,9 @@ public class BubbleExperimentConfig {
private static final String WHITELISTED_AUTO_BUBBLE_APPS = "whitelisted_auto_bubble_apps";
+ private static final String ALLOW_BUBBLE_MENU = "allow_bubble_screenshot_menu";
+ private static final boolean ALLOW_BUBBLE_MENU_DEFAULT = false;
+
/**
* When true, if a notification has the information necessary to bubble (i.e. valid
* contentIntent and an icon or image), then a {@link android.app.Notification.BubbleMetadata}
@@ -123,6 +126,16 @@ public class BubbleExperimentConfig {
}
/**
+ * When true, show a menu when a bubble is long-pressed, which will allow the user to take
+ * actions on that bubble.
+ */
+ static boolean allowBubbleScreenshotMenu(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ ALLOW_BUBBLE_MENU,
+ ALLOW_BUBBLE_MENU_DEFAULT ? 1 : 0) != 0;
+ }
+
+ /**
* If {@link #allowAnyNotifToBubble(Context)} is true, this method creates and adds
* {@link android.app.Notification.BubbleMetadata} to the notification entry as long as
* the notification has necessary info for BubbleMetadata.
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleMenuView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleMenuView.java
new file mode 100644
index 000000000000..e8eb72e8392f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleMenuView.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bubbles;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.android.systemui.R;
+
+/**
+ * Menu which allows users to take actions on bubbles, ex. screenshots.
+ */
+public class BubbleMenuView extends FrameLayout {
+ private FrameLayout mMenu;
+ private boolean mShowing = false;
+
+ public BubbleMenuView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public BubbleMenuView(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mMenu = findViewById(R.id.bubble_menu_view);
+ ImageView icon = findViewById(com.android.internal.R.id.icon);
+ icon.setImageDrawable(mContext.getDrawable(com.android.internal.R.drawable.ic_screenshot));
+ }
+
+ /**
+ * Get the bubble menu view.
+ */
+ public View getMenuView() {
+ return mMenu;
+ }
+
+ /**
+ * Checks whether the bubble menu is currently displayed.
+ */
+ public boolean isShowing() {
+ return mShowing;
+ }
+
+ /**
+ * Show the bubble menu at the specified position on the screen.
+ */
+ public void show(float x, float y) {
+ mShowing = true;
+ this.setVisibility(VISIBLE);
+ mMenu.setTranslationX(x);
+ mMenu.setTranslationY(y);
+ }
+
+ /**
+ * Hide the bubble menu.
+ */
+ public void hide() {
+ mShowing = false;
+ this.setVisibility(GONE);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 29de2f049690..29a4bb1fca84 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -110,6 +110,7 @@ public class BubbleStackView extends FrameLayout {
/** How long to wait, in milliseconds, before hiding the flyout. */
@VisibleForTesting
static final int FLYOUT_HIDE_AFTER = 5000;
+ private BubbleController.BubbleScreenshotListener mBubbleScreenshotListener;
/**
* Interface to synchronize {@link View} state and the screen.
@@ -163,6 +164,7 @@ public class BubbleStackView extends FrameLayout {
private ExpandedAnimationController mExpandedAnimationController;
private FrameLayout mExpandedViewContainer;
+ @Nullable private BubbleMenuView mBubbleMenuView;
private BubbleFlyoutView mFlyout;
/** Runnable that fades out the flyout and then sets it to GONE. */
@@ -194,6 +196,7 @@ public class BubbleStackView extends FrameLayout {
private int mPointerHeight;
private int mStatusBarHeight;
private int mImeOffset;
+ private int mBubbleMenuOffset = 252;
private BubbleIconFactory mBubbleIconFactory;
private Bubble mExpandedBubble;
private boolean mIsExpanded;
@@ -492,6 +495,9 @@ public class BubbleStackView extends FrameLayout {
mDesaturateAndDarkenPaint.setColorFilter(new ColorMatrixColorFilter(animatedMatrix));
mDesaturateAndDarkenTargetView.setLayerPaint(mDesaturateAndDarkenPaint);
});
+
+ mInflater.inflate(R.layout.bubble_menu_view, this);
+ mBubbleMenuView = findViewById(R.id.bubble_menu_container);
}
private void setUpFlyout() {
@@ -683,6 +689,13 @@ public class BubbleStackView extends FrameLayout {
}
/**
+ * Sets the screenshot listener.
+ */
+ public void setBubbleScreenshotListener(BubbleController.BubbleScreenshotListener listener) {
+ mBubbleScreenshotListener = listener;
+ }
+
+ /**
* Whether the stack of bubbles is expanded or not.
*/
public boolean isExpanded() {
@@ -870,6 +883,12 @@ public class BubbleStackView extends FrameLayout {
public View getTargetView(MotionEvent event) {
float x = event.getRawX();
float y = event.getRawY();
+ if (mBubbleMenuView.isShowing()) {
+ if (isIntersecting(mBubbleMenuView.getMenuView(), x, y)) {
+ return mBubbleMenuView;
+ }
+ return null;
+ }
if (mIsExpanded) {
if (isIntersecting(mBubbleContainer, x, y)) {
// Could be tapping or dragging a bubble while expanded
@@ -1074,6 +1093,7 @@ public class BubbleStackView extends FrameLayout {
return;
}
+ hideBubbleMenu();
mStackAnimationController.cancelStackPositionAnimations();
mBubbleContainer.setActiveController(mStackAnimationController);
hideFlyoutImmediate();
@@ -1473,6 +1493,11 @@ public class BubbleStackView extends FrameLayout {
@Override
public void getBoundsOnScreen(Rect outRect) {
+ // If the bubble menu is open, the entire screen should capture touch events.
+ if (mBubbleMenuView.isShowing()) {
+ outRect.set(0, 0, getWidth(), getHeight());
+ return;
+ }
if (!mIsExpanded) {
if (mBubbleContainer.getChildCount() > 0) {
mBubbleContainer.getChildAt(0).getBoundsOnScreen(outRect);
@@ -1700,4 +1725,43 @@ public class BubbleStackView extends FrameLayout {
}
return bubbles;
}
+
+ /**
+ * Show the bubble menu, positioned relative to the stack.
+ */
+ public void showBubbleMenu() {
+ PointF currentPos = mStackAnimationController.getStackPosition();
+ float yPos = currentPos.y;
+ float xPos = currentPos.x;
+ if (mStackAnimationController.isStackOnLeftSide()) {
+ xPos += mBubbleSize;
+ } else {
+ //TODO: Use the width of the menu instead of this fixed offset. Offset used for now
+ // because menu width isn't correct the first time the menu is shown.
+ xPos -= mBubbleMenuOffset;
+ }
+
+ mBubbleMenuView.show(xPos, yPos);
+ }
+
+ /**
+ * Hide the bubble menu.
+ */
+ public void hideBubbleMenu() {
+ mBubbleMenuView.hide();
+ }
+
+ /**
+ * Determines whether the bubble menu is currently showing.
+ */
+ public boolean isShowingBubbleMenu() {
+ return mBubbleMenuView.isShowing();
+ }
+
+ /**
+ * Take a screenshot and send it to the specified bubble.
+ */
+ public void sendScreenshotToBubble(Bubble bubble) {
+ mBubbleScreenshotListener.onBubbleScreenshot(bubble);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
index 44e013a34f54..b1d205c79c99 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
@@ -57,6 +57,7 @@ class BubbleTouchHandler implements View.OnTouchListener {
private final PointF mViewPositionOnTouchDown = new PointF();
private final BubbleStackView mStack;
private final BubbleData mBubbleData;
+ private final Context mContext;
private BubbleController mController = Dependency.get(BubbleController.class);
@@ -75,6 +76,7 @@ class BubbleTouchHandler implements View.OnTouchListener {
mTouchSlopSquared = touchSlop * touchSlop;
mBubbleData = bubbleData;
mStack = stackView;
+ mContext = context;
}
@Override
@@ -91,15 +93,24 @@ class BubbleTouchHandler implements View.OnTouchListener {
// anything, collapse the stack.
if (action == MotionEvent.ACTION_OUTSIDE || mTouchedView == null) {
mBubbleData.setExpanded(false);
+ mStack.hideBubbleMenu();
resetForNextGesture();
return false;
}
+ if (mTouchedView instanceof BubbleMenuView) {
+ mStack.hideBubbleMenu();
+ resetForNextGesture();
+ mStack.sendScreenshotToBubble(mBubbleData.getSelectedBubble());
+ return false;
+ }
+
if (!(mTouchedView instanceof BadgedImageView)
&& !(mTouchedView instanceof BubbleStackView)
&& !(mTouchedView instanceof BubbleFlyoutView)) {
// Not touching anything touchable, but we shouldn't collapse (e.g. touching edge
// of expanded view).
+ mStack.hideBubbleMenu();
resetForNextGesture();
return false;
}
@@ -132,6 +143,10 @@ class BubbleTouchHandler implements View.OnTouchListener {
break;
case MotionEvent.ACTION_MOVE:
+ // block all further touch inputs once the menu is open
+ if (mStack.isShowingBubbleMenu()) {
+ return true;
+ }
trackMovement(event);
final float deltaX = rawX - mTouchDown.x;
final float deltaY = rawY - mTouchDown.y;
@@ -148,6 +163,13 @@ class BubbleTouchHandler implements View.OnTouchListener {
} else {
mStack.onBubbleDragged(mTouchedView, viewX, viewY);
}
+ } else {
+ float touchTime = event.getEventTime() - event.getDownTime();
+ if (touchTime > ViewConfiguration.getLongPressTimeout() && !mStack.isExpanded()
+ && BubbleExperimentConfig.allowBubbleScreenshotMenu(mContext)) {
+ mStack.showBubbleMenu();
+ return true;
+ }
}
final boolean currentlyInDismissTarget = mStack.isInDismissTarget(event);
@@ -171,6 +193,10 @@ class BubbleTouchHandler implements View.OnTouchListener {
break;
case MotionEvent.ACTION_UP:
+ if (mStack.isShowingBubbleMenu()) {
+ resetForNextGesture();
+ return true;
+ }
trackMovement(event);
mVelocityTracker.computeCurrentVelocity(/* maxVelocity */ 1000);
final float velX = mVelocityTracker.getXVelocity();
@@ -261,7 +287,6 @@ class BubbleTouchHandler implements View.OnTouchListener {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
-
mTouchedView = null;
mMovedEnough = false;
mInDismissTarget = false;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 4c707f45efc1..ae43aa2f4118 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -82,6 +82,7 @@ import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.InjectionInflationController;
@@ -153,6 +154,8 @@ public class BubbleControllerTest extends SysuiTestCase {
private Resources mResources;
@Mock
private Lazy<ShadeController> mShadeController;
+ @Mock
+ private RemoteInputUriController mRemoteInputUriController;
private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
private BubbleData mBubbleData;
@@ -212,7 +215,8 @@ public class BubbleControllerTest extends SysuiTestCase {
mZenModeController,
mLockscreenUserManager,
mNotificationGroupManager,
- mNotificationEntryManager);
+ mNotificationEntryManager,
+ mRemoteInputUriController);
mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener);
mBubbleController.setExpandListener(mBubbleExpandListener);
@@ -708,11 +712,13 @@ public class BubbleControllerTest extends SysuiTestCase {
ZenModeController zenModeController,
NotificationLockscreenUserManager lockscreenUserManager,
NotificationGroupManager groupManager,
- NotificationEntryManager entryManager) {
+ NotificationEntryManager entryManager,
+ RemoteInputUriController remoteInputUriController) {
super(context,
statusBarWindowController, statusBarStateController, shadeController,
data, Runnable::run, configurationController, interruptionStateProvider,
- zenModeController, lockscreenUserManager, groupManager, entryManager);
+ zenModeController, lockscreenUserManager, groupManager, entryManager,
+ remoteInputUriController);
}
}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index e79a2897d86a..840b7af19890 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
import static android.Manifest.permission.SHUTDOWN;
@@ -737,7 +738,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
//
@Override
public String[] listInterfaces() {
- NetworkStack.checkNetworkStackPermission(mContext);
+ // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
+ // APIs.
+ NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
try {
return mNetdService.interfaceGetList();
} catch (RemoteException | ServiceSpecificException e) {
@@ -787,7 +790,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
@Override
public InterfaceConfiguration getInterfaceConfig(String iface) {
- NetworkStack.checkNetworkStackPermission(mContext);
+ // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
+ // APIs.
+ NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
final InterfaceConfigurationParcel result;
try {
result = mNetdService.interfaceGetCfg(iface);
@@ -805,7 +810,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
@Override
public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
- NetworkStack.checkNetworkStackPermission(mContext);
+ // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
+ // APIs.
+ NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
LinkAddress linkAddr = cfg.getLinkAddress();
if (linkAddr == null || linkAddr.getAddress() == null) {
throw new IllegalStateException("Null LinkAddress given");
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 12debbff3e90..521b39305d9d 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -57,6 +57,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
@@ -81,6 +82,22 @@ public class PackageWatchdog {
static final String PROPERTY_WATCHDOG_EXPLICIT_HEALTH_CHECK_ENABLED =
"watchdog_explicit_health_check_enabled";
+ public static final int FAILURE_REASON_UNKNOWN = 0;
+ public static final int FAILURE_REASON_NATIVE_CRASH = 1;
+ public static final int FAILURE_REASON_EXPLICIT_HEALTH_CHECK = 2;
+ public static final int FAILURE_REASON_APP_CRASH = 3;
+ public static final int FAILURE_REASON_APP_NOT_RESPONDING = 4;
+
+ @IntDef(prefix = { "FAILURE_REASON_" }, value = {
+ FAILURE_REASON_UNKNOWN,
+ FAILURE_REASON_NATIVE_CRASH,
+ FAILURE_REASON_EXPLICIT_HEALTH_CHECK,
+ FAILURE_REASON_APP_CRASH,
+ FAILURE_REASON_APP_NOT_RESPONDING
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface FailureReasons {}
+
// Duration to count package failures before it resets to 0
@VisibleForTesting
static final int DEFAULT_TRIGGER_FAILURE_DURATION_MS =
@@ -305,14 +322,15 @@ public class PackageWatchdog {
}
/**
- * Called when a process fails either due to a crash or ANR.
+ * Called when a process fails due to a crash, ANR or explicit health check.
*
* <p>For each package contained in the process, one registered observer with the least user
* impact will be notified for mitigation.
*
* <p>This method could be called frequently if there is a severe problem on the device.
*/
- public void onPackageFailure(List<VersionedPackage> packages) {
+ public void onPackageFailure(List<VersionedPackage> packages,
+ @FailureReasons int failureReason) {
mLongTaskHandler.post(() -> {
synchronized (mLock) {
if (mAllObservers.isEmpty()) {
@@ -343,7 +361,7 @@ public class PackageWatchdog {
// Execute action with least user impact
if (currentObserverToNotify != null) {
- currentObserverToNotify.execute(versionedPackage);
+ currentObserverToNotify.execute(versionedPackage, failureReason);
}
}
}
@@ -414,7 +432,7 @@ public class PackageWatchdog {
*
* @return {@code true} if action was executed successfully, {@code false} otherwise
*/
- boolean execute(VersionedPackage versionedPackage);
+ boolean execute(VersionedPackage versionedPackage, @FailureReasons int failureReason);
// TODO(b/120598832): Ensure uniqueness?
/**
@@ -659,7 +677,8 @@ public class PackageWatchdog {
while (it.hasNext()) {
VersionedPackage versionedPkg = it.next().mPackage;
Slog.i(TAG, "Explicit health check failed for package " + versionedPkg);
- registeredObserver.execute(versionedPkg);
+ registeredObserver.execute(versionedPkg,
+ PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
}
}
}
@@ -770,7 +789,7 @@ public class PackageWatchdog {
final List<VersionedPackage> pkgList = Collections.singletonList(pkg);
final long failureCount = getTriggerFailureCount();
for (int i = 0; i < failureCount; i++) {
- onPackageFailure(pkgList);
+ onPackageFailure(pkgList, FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
}
});
}
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 51e1718d4c98..83a7341923fa 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -446,7 +446,8 @@ class AppErrors {
RescueParty.noteAppCrash(mContext, r.uid);
}
- mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode());
+ mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode(),
+ PackageWatchdog.FAILURE_REASON_APP_CRASH);
}
final int relaunchReason = r != null
@@ -900,7 +901,8 @@ class AppErrors {
}
// Notify PackageWatchdog without the lock held
if (packageList != null) {
- mPackageWatchdog.onPackageFailure(packageList);
+ mPackageWatchdog.onPackageFailure(packageList,
+ PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING);
}
}
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 38030c248139..cf996a50d5c7 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -125,7 +125,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
// Keep the last WiFi stats so we can compute a delta.
@GuardedBy("mWorkerLock")
private WifiActivityEnergyInfo mLastInfo =
- new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0, 0);
+ new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0);
/**
* Timestamp at which all external stats were last collected in
diff --git a/services/core/java/com/android/server/integrity/model/BitInputStream.java b/services/core/java/com/android/server/integrity/model/BitInputStream.java
index 09bc7e8b9861..e768fe6626ac 100644
--- a/services/core/java/com/android/server/integrity/model/BitInputStream.java
+++ b/services/core/java/com/android/server/integrity/model/BitInputStream.java
@@ -16,15 +16,29 @@
package com.android.server.integrity.model;
+import java.io.IOException;
+import java.io.InputStream;
+
/** A wrapper class for reading a stream of bits. */
public class BitInputStream {
- private byte[] mRuleBytes;
private long mBitPointer;
+ private boolean mReadFromStream;
+
+ private byte[] mRuleBytes;
+ private InputStream mRuleInputStream;
+
+ private byte mCurrentRuleByte;
public BitInputStream(byte[] ruleBytes) {
this.mRuleBytes = ruleBytes;
this.mBitPointer = 0;
+ this.mReadFromStream = false;
+ }
+
+ public BitInputStream(InputStream ruleInputStream) {
+ this.mRuleInputStream = ruleInputStream;
+ this.mReadFromStream = true;
}
/**
@@ -33,34 +47,43 @@ public class BitInputStream {
* @param numOfBits The number of bits to read.
* @return The value read from the stream.
*/
- public int getNext(int numOfBits) {
+ public int getNext(int numOfBits) throws IOException {
int component = 0;
int count = 0;
- int idx = (int) (mBitPointer / 8);
- int offset = 7 - (int) (mBitPointer % 8);
-
while (count++ < numOfBits) {
- if (idx >= mRuleBytes.length) {
- throw new IllegalArgumentException(String.format("Invalid byte index: %d", idx));
+ if (mBitPointer % 8 == 0) {
+ mCurrentRuleByte = getNextByte();
}
+ int offset = 7 - (int) (mBitPointer % 8);
component <<= 1;
- component |= (mRuleBytes[idx] >>> offset) & 1;
+ component |= (mCurrentRuleByte >>> offset) & 1;
- offset--;
- if (offset == -1) {
- idx++;
- offset = 7;
- }
+ mBitPointer++;
}
- mBitPointer += numOfBits;
return component;
}
/** Check if there are bits left in the stream. */
- public boolean hasNext() {
- return mBitPointer / 8 < mRuleBytes.length;
+ public boolean hasNext() throws IOException {
+ if (mReadFromStream) {
+ return mRuleInputStream.available() > 0;
+ } else {
+ return mBitPointer / 8 < mRuleBytes.length;
+ }
+ }
+
+ private byte getNextByte() throws IOException {
+ if (mReadFromStream) {
+ return (byte) mRuleInputStream.read();
+ } else {
+ int idx = (int) (mBitPointer / 8);
+ if (idx >= mRuleBytes.length) {
+ throw new IllegalArgumentException(String.format("Invalid byte index: %d", idx));
+ }
+ return mRuleBytes[idx];
+ }
}
}
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 8aa0751af11c..3ef45a637bc1 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
@@ -36,6 +36,7 @@ import android.content.integrity.Rule;
import com.android.server.integrity.model.BitInputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@@ -56,15 +57,14 @@ public class RuleBinaryParser implements RuleParser {
@Override
public List<Rule> parse(InputStream inputStream) throws RuleParseException {
try {
- byte[] ruleBytes = new byte[inputStream.available()];
- inputStream.read(ruleBytes);
- return parse(ruleBytes);
+ BitInputStream bitInputStream = new BitInputStream(inputStream);
+ return parseRules(bitInputStream);
} catch (Exception e) {
throw new RuleParseException(e.getMessage(), e);
}
}
- private List<Rule> parseRules(BitInputStream bitInputStream) {
+ private List<Rule> parseRules(BitInputStream bitInputStream) throws IOException {
List<Rule> parsedRules = new ArrayList<>();
// Read the rule binary file format version.
@@ -79,7 +79,7 @@ public class RuleBinaryParser implements RuleParser {
return parsedRules;
}
- private Rule parseRule(BitInputStream bitInputStream) {
+ private Rule parseRule(BitInputStream bitInputStream) throws IOException {
Formula formula = parseFormula(bitInputStream);
int effect = bitInputStream.getNext(EFFECT_BITS);
@@ -90,7 +90,7 @@ public class RuleBinaryParser implements RuleParser {
return new Rule(formula, effect);
}
- private Formula parseFormula(BitInputStream bitInputStream) {
+ private Formula parseFormula(BitInputStream bitInputStream) throws IOException {
int separator = bitInputStream.getNext(SEPARATOR_BITS);
switch (separator) {
case ATOMIC_FORMULA_START:
@@ -105,7 +105,7 @@ public class RuleBinaryParser implements RuleParser {
}
}
- private CompoundFormula parseCompoundFormula(BitInputStream bitInputStream) {
+ private CompoundFormula parseCompoundFormula(BitInputStream bitInputStream) throws IOException {
int connector = bitInputStream.getNext(CONNECTOR_BITS);
List<Formula> formulas = new ArrayList<>();
@@ -118,7 +118,7 @@ public class RuleBinaryParser implements RuleParser {
return new CompoundFormula(connector, formulas);
}
- private AtomicFormula parseAtomicFormula(BitInputStream bitInputStream) {
+ private AtomicFormula parseAtomicFormula(BitInputStream bitInputStream) throws IOException {
int key = bitInputStream.getNext(KEY_BITS);
int operator = bitInputStream.getNext(OPERATOR_BITS);
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 b988fd4c40f1..fdbb7d9df293 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
@@ -127,7 +127,7 @@ public class RuleBinarySerializer implements RuleSerializer {
bitOutputStream.setNext(SEPARATOR_BITS, ATOMIC_FORMULA_START);
bitOutputStream.setNext(KEY_BITS, atomicFormula.getKey());
- if (atomicFormula instanceof AtomicFormula.StringAtomicFormula) {
+ if (atomicFormula.getTag() == AtomicFormula.STRING_ATOMIC_FORMULA_TAG) {
AtomicFormula.StringAtomicFormula stringAtomicFormula =
(AtomicFormula.StringAtomicFormula) atomicFormula;
bitOutputStream.setNext(OPERATOR_BITS, AtomicFormula.EQ);
@@ -135,7 +135,7 @@ public class RuleBinarySerializer implements RuleSerializer {
stringAtomicFormula.getValue(),
stringAtomicFormula.getIsHashedValue(),
bitOutputStream);
- } else if (atomicFormula instanceof AtomicFormula.IntAtomicFormula) {
+ } else if (atomicFormula.getTag() == AtomicFormula.INT_ATOMIC_FORMULA_TAG) {
AtomicFormula.IntAtomicFormula intAtomicFormula =
(AtomicFormula.IntAtomicFormula) atomicFormula;
bitOutputStream.setNext(OPERATOR_BITS, intAtomicFormula.getOperator());
@@ -143,7 +143,7 @@ public class RuleBinarySerializer implements RuleSerializer {
String.valueOf(intAtomicFormula.getValue()),
/* isHashedValue= */ false,
bitOutputStream);
- } else if (atomicFormula instanceof AtomicFormula.BooleanAtomicFormula) {
+ } else if (atomicFormula.getTag() == AtomicFormula.BOOLEAN_ATOMIC_FORMULA_TAG) {
AtomicFormula.BooleanAtomicFormula booleanAtomicFormula =
(AtomicFormula.BooleanAtomicFormula) atomicFormula;
bitOutputStream.setNext(OPERATOR_BITS, AtomicFormula.EQ);
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 72068ceeb4f0..cfe50c6c8ac9 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
@@ -127,7 +127,7 @@ public class RuleXmlSerializer implements RuleSerializer {
xmlSerializer.startTag(NAMESPACE, ATOMIC_FORMULA_TAG);
serializeAttributeValue(
KEY_ATTRIBUTE, String.valueOf(atomicFormula.getKey()), xmlSerializer);
- if (atomicFormula instanceof AtomicFormula.StringAtomicFormula) {
+ if (atomicFormula.getTag() == AtomicFormula.STRING_ATOMIC_FORMULA_TAG) {
serializeAttributeValue(
VALUE_ATTRIBUTE,
((AtomicFormula.StringAtomicFormula) atomicFormula).getValue(),
@@ -137,7 +137,7 @@ public class RuleXmlSerializer implements RuleSerializer {
String.valueOf(
((AtomicFormula.StringAtomicFormula) atomicFormula).getIsHashedValue()),
xmlSerializer);
- } else if (atomicFormula instanceof AtomicFormula.IntAtomicFormula) {
+ } else if (atomicFormula.getTag() == AtomicFormula.INT_ATOMIC_FORMULA_TAG) {
serializeAttributeValue(
OPERATOR_ATTRIBUTE,
String.valueOf(((AtomicFormula.IntAtomicFormula) atomicFormula).getOperator()),
@@ -146,7 +146,7 @@ public class RuleXmlSerializer implements RuleSerializer {
VALUE_ATTRIBUTE,
String.valueOf(((AtomicFormula.IntAtomicFormula) atomicFormula).getValue()),
xmlSerializer);
- } else if (atomicFormula instanceof AtomicFormula.BooleanAtomicFormula) {
+ } else if (atomicFormula.getTag() == AtomicFormula.BOOLEAN_ATOMIC_FORMULA_TAG) {
serializeAttributeValue(
VALUE_ATTRIBUTE,
String.valueOf(((AtomicFormula.BooleanAtomicFormula) atomicFormula).getValue()),
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 83b62159f9b0..ec4aedd01cea 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -379,7 +379,7 @@ public class LockSettingsService extends ILockSettings.Stub {
if (DEBUG) Slog.v(TAG, "Tie managed profile to parent now!");
try (LockscreenCredential unifiedProfilePassword = generateRandomProfilePassword()) {
setLockCredentialInternal(unifiedProfilePassword, managedUserPassword, managedUserId,
- false, /* isLockTiedToParent= */ true);
+ /* isLockTiedToParent= */ true);
tieProfileLockToParent(managedUserId, unifiedProfilePassword);
}
}
@@ -1473,17 +1473,12 @@ public class LockSettingsService extends ILockSettings.Stub {
setLockCredentialInternal(LockscreenCredential.createNone(),
profilePasswordMap.get(managedUserId),
managedUserId,
- false, /* isLockTiedToParent= */ true);
+ /* isLockTiedToParent= */ true);
+ mStorage.removeChildProfileLock(managedUserId);
+ removeKeystoreProfileKey(managedUserId);
} else {
- Slog.wtf(TAG, "clear tied profile challenges, but no password supplied.");
- // Attempt an untrusted reset by supplying an empty credential.
- setLockCredentialInternal(LockscreenCredential.createNone(),
- LockscreenCredential.createNone(),
- managedUserId,
- true, /* isLockTiedToParent= */ true);
+ Slog.wtf(TAG, "Attempt to clear tied challenge, but no password supplied.");
}
- mStorage.removeChildProfileLock(managedUserId);
- removeKeystoreProfileKey(managedUserId);
}
}
}
@@ -1567,7 +1562,7 @@ public class LockSettingsService extends ILockSettings.Stub {
// should call setLockCredentialInternal.
@Override
public boolean setLockCredential(LockscreenCredential credential,
- LockscreenCredential savedCredential, int userId, boolean allowUntrustedChange) {
+ LockscreenCredential savedCredential, int userId) {
if (!mLockPatternUtils.hasSecureLockScreen()) {
throw new UnsupportedOperationException(
@@ -1576,7 +1571,7 @@ public class LockSettingsService extends ILockSettings.Stub {
checkWritePermission(userId);
synchronized (mSeparateChallengeLock) {
if (!setLockCredentialInternal(credential, savedCredential,
- userId, allowUntrustedChange, /* isLockTiedToParent= */ false)) {
+ userId, /* isLockTiedToParent= */ false)) {
return false;
}
setSeparateProfileChallengeEnabledLocked(userId, true, /* unused */ null);
@@ -1598,14 +1593,13 @@ public class LockSettingsService extends ILockSettings.Stub {
* credentials are being tied to its parent's credentials.
*/
private boolean setLockCredentialInternal(LockscreenCredential credential,
- LockscreenCredential savedCredential, int userId,
- boolean allowUntrustedChange, boolean isLockTiedToParent) {
+ LockscreenCredential savedCredential, int userId, boolean isLockTiedToParent) {
Preconditions.checkNotNull(credential);
Preconditions.checkNotNull(savedCredential);
synchronized (mSpManager) {
if (isSyntheticPasswordBasedCredentialLocked(userId)) {
return spBasedSetLockCredentialInternalLocked(credential, savedCredential, userId,
- allowUntrustedChange, isLockTiedToParent);
+ isLockTiedToParent);
}
}
@@ -1653,7 +1647,7 @@ public class LockSettingsService extends ILockSettings.Stub {
if (shouldMigrateToSyntheticPasswordLocked(userId)) {
initializeSyntheticPasswordLocked(currentHandle.hash, savedCredential, userId);
return spBasedSetLockCredentialInternalLocked(credential, savedCredential, userId,
- allowUntrustedChange, isLockTiedToParent);
+ isLockTiedToParent);
}
}
if (DEBUG) Slog.d(TAG, "setLockCredentialInternal: user=" + userId);
@@ -2075,7 +2069,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
if (shouldReEnroll) {
setLockCredentialInternal(credential, credential,
- userId, false, /* isLockTiedToParent= */ false);
+ userId, /* isLockTiedToParent= */ false);
} else {
// Now that we've cleared of all required GK migration, let's do the final
// migration to synthetic password.
@@ -2210,7 +2204,6 @@ public class LockSettingsService extends ILockSettings.Stub {
Slog.i(TAG, "RemoveUser: " + userId);
mSpManager.removeUser(userId);
mStrongAuth.removeUser(userId);
- tryRemoveUserFromSpCacheLater(userId);
final KeyStore ks = KeyStore.getInstance();
ks.onUserRemoved(userId);
@@ -2471,25 +2464,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
}
- /**
- * A user's synthetic password does not change so it must be cached in certain circumstances to
- * enable untrusted credential reset.
- *
- * Untrusted credential reset will be removed in a future version (b/68036371) at which point
- * this cache is no longer needed as the SP will always be known when changing the user's
- * credential.
- */
- @GuardedBy("mSpManager")
- private SparseArray<AuthenticationToken> mSpCache = new SparseArray<>();
-
private void onAuthTokenKnownForUser(@UserIdInt int userId, AuthenticationToken auth) {
- // Preemptively cache the SP and then try to remove it in a handler.
- Slog.i(TAG, "Caching SP for user " + userId);
- synchronized (mSpManager) {
- mSpCache.put(userId, auth);
- }
- tryRemoveUserFromSpCacheLater(userId);
-
if (mInjector.isGsiRunning()) {
Slog.w(TAG, "AuthSecret disabled in GSI");
return;
@@ -2510,42 +2485,6 @@ public class LockSettingsService extends ILockSettings.Stub {
}
}
- private void tryRemoveUserFromSpCacheLater(@UserIdInt int userId) {
- mHandler.post(() -> {
- if (!shouldCacheSpForUser(userId)) {
- // The transition from 'should not cache' to 'should cache' can only happen if
- // certain admin apps are installed after provisioning e.g. via adb. This is not
- // a common case and we do not seamlessly support; it may result in the SP not
- // being cached when it is needed. The cache can be re-populated by verifying
- // the credential again.
- Slog.i(TAG, "Removing SP from cache for user " + userId);
- synchronized (mSpManager) {
- mSpCache.remove(userId);
- }
- }
- });
- }
-
- /** Do not hold any of the locks from this service when calling. */
- private boolean shouldCacheSpForUser(@UserIdInt int userId) {
- // Before the user setup has completed, an admin could be installed that requires the SP to
- // be cached (see below).
- if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.USER_SETUP_COMPLETE, 0, userId) == 0) {
- return true;
- }
-
- // If the user has an admin which can perform an untrusted credential reset, the SP needs to
- // be cached. If there isn't a DevicePolicyManager then there can't be an admin in the first
- // place so caching is not necessary.
- final DevicePolicyManagerInternal dpmi = LocalServices.getService(
- DevicePolicyManagerInternal.class);
- if (dpmi == null) {
- return false;
- }
- return dpmi.canUserHaveUntrustedCredentialReset(userId);
- }
-
/**
* Precondition: vold and keystore unlocked.
*
@@ -2579,8 +2518,8 @@ public class LockSettingsService extends ILockSettings.Stub {
* This could also happen during an untrusted reset to clear password.
*
* 3. credentialhash == null and credential != null
- * This is the untrusted credential reset, OR the user sets a new lockscreen password
- * FOR THE FIRST TIME on a SP-enabled device. New credential and new SID will be created
+ * The user sets a new lockscreen password FOR THE FIRST TIME on a SP-enabled device.
+ * New credential and new SID will be created
*/
@GuardedBy("mSpManager")
@VisibleForTesting
@@ -2905,8 +2844,7 @@ public class LockSettingsService extends ILockSettings.Stub {
*/
@GuardedBy("mSpManager")
private boolean spBasedSetLockCredentialInternalLocked(LockscreenCredential credential,
- LockscreenCredential savedCredential, int userId,
- boolean allowUntrustedChange, boolean isLockTiedToParent) {
+ LockscreenCredential savedCredential, int userId, boolean isLockTiedToParent) {
if (DEBUG) Slog.d(TAG, "spBasedSetLockCredentialInternalLocked: user=" + userId);
if (savedCredential.isNone() && isManagedProfileWithUnifiedLock(userId)) {
// get credential from keystore when managed profile has unified lock
@@ -2927,50 +2865,24 @@ public class LockSettingsService extends ILockSettings.Stub {
VerifyCredentialResponse response = authResult.gkResponse;
AuthenticationToken auth = authResult.authToken;
- // If existing credential is provided, the existing credential must match.
- if (!savedCredential.isNone() && auth == null) {
- Slog.w(TAG, "Failed to enroll: incorrect credential");
- return false;
- }
- boolean untrustedReset = false;
- if (auth != null) {
- onAuthTokenKnownForUser(userId, auth);
- } else if (response == null) {
- throw new IllegalStateException("Password change failed.");
- } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR) {
- // We are performing an untrusted credential change, by DevicePolicyManager or other
- // internal callers that don't provide the existing credential
- Slog.w(TAG, "Untrusted credential change invoked");
- // Try to get a cached auth token, so we can keep SP unchanged.
- auth = mSpCache.get(userId);
- if (!allowUntrustedChange) {
- throw new IllegalStateException("Untrusted credential change was invoked but it was"
- + " not allowed. This is likely a bug. Auth token is null: "
- + Boolean.toString(auth == null));
- }
- untrustedReset = true;
- } else /* responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ {
- Slog.w(TAG, "Rate limit exceeded, so password was not changed.");
- return false;
- }
- if (auth != null) {
- if (untrustedReset) {
- // Force change the current SID to mantain existing behaviour that an untrusted
- // reset leads to a change of SID. If the untrusted reset is for clearing the
- // current password, the nuking of the SID will be done in
- // setLockCredentialWithAuthTokenLocked next
- mSpManager.newSidForUser(getGateKeeperService(), auth, userId);
+ if (auth == null) {
+ if (response == null
+ || response.getResponseCode() == VerifyCredentialResponse.RESPONSE_ERROR) {
+ Slog.w(TAG, "Failed to enroll: incorrect credential.");
+ return false;
}
- setLockCredentialWithAuthTokenLocked(credential, auth, userId);
- mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
- } else {
- throw new IllegalStateException(
- "Untrusted credential reset not possible without cached SP");
- // Could call initializeSyntheticPasswordLocked(null, credential, credentialType,
- // requestedQuality, userId) instead if we still allow untrusted reset that changes
- // synthetic password. That would invalidate existing escrow tokens though.
+ if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
+ Slog.w(TAG, "Failed to enroll: rate limit exceeded.");
+ return false;
+ }
+ // Should not be reachable, but just in case.
+ throw new IllegalStateException("password change failed");
}
+
+ onAuthTokenKnownForUser(userId, auth);
+ setLockCredentialWithAuthTokenLocked(credential, auth, userId);
+ mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
sendCredentialsOnChangeIfRequired(credential, userId, isLockTiedToParent);
return true;
}
@@ -3125,11 +3037,10 @@ public class LockSettingsService extends ILockSettings.Stub {
+ "verification.");
return false;
}
+ onAuthTokenKnownForUser(userId, result.authToken);
long oldHandle = getSyntheticPasswordHandleLocked(userId);
setLockCredentialWithAuthTokenLocked(credential, result.authToken, userId);
mSpManager.destroyPasswordBasedSyntheticPassword(oldHandle, userId);
-
- onAuthTokenKnownForUser(userId, result.authToken);
return true;
}
@@ -3248,8 +3159,6 @@ public class LockSettingsService extends ILockSettings.Stub {
private class DeviceProvisionedObserver extends ContentObserver {
private final Uri mDeviceProvisionedUri = Settings.Global.getUriFor(
Settings.Global.DEVICE_PROVISIONED);
- private final Uri mUserSetupCompleteUri = Settings.Secure.getUriFor(
- Settings.Secure.USER_SETUP_COMPLETE);
private boolean mRegistered;
@@ -3267,8 +3176,6 @@ public class LockSettingsService extends ILockSettings.Stub {
reportDeviceSetupComplete();
clearFrpCredentialIfOwnerNotSecure();
}
- } else if (mUserSetupCompleteUri.equals(uri)) {
- tryRemoveUserFromSpCacheLater(userId);
}
}
@@ -3320,8 +3227,6 @@ public class LockSettingsService extends ILockSettings.Stub {
if (register) {
mContext.getContentResolver().registerContentObserver(mDeviceProvisionedUri,
false, this);
- mContext.getContentResolver().registerContentObserver(mUserSetupCompleteUri,
- false, this, UserHandle.USER_ALL);
} else {
mContext.getContentResolver().unregisterContentObserver(this);
}
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index e9a8085950b0..c53647d053bc 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -136,8 +136,13 @@ public class SyntheticPasswordManager {
"android-synthetic-password-personalization-context".getBytes();
static class AuthenticationResult {
- public AuthenticationToken authToken;
- public VerifyCredentialResponse gkResponse;
+ // Non-null if password/token passes verification, null otherwise
+ @Nullable public AuthenticationToken authToken;
+ // OK: password / token passes verification, user has a lockscreen
+ // null: user does not have a lockscreen (but password / token passes verification)
+ // ERROR: password / token fails verification
+ // RETRY: password / token verification is throttled at the moment.
+ @Nullable public VerifyCredentialResponse gkResponse;
}
/**
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d0ad47d3d7a6..12afef2cf950 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -171,6 +171,7 @@ import android.os.IDeviceIdleController;
import android.os.IInterface;
import android.os.Looper;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -292,6 +293,9 @@ public class NotificationManagerService extends SystemService {
public static final boolean ENABLE_CHILD_NOTIFICATIONS
= SystemProperties.getBoolean("debug.child_notifs", true);
+ // pullStats report request: undecorated remote view stats
+ public static final int REPORT_REMOTE_VIEWS = 0x01;
+
static final boolean DEBUG_INTERRUPTIVENESS = SystemProperties.getBoolean(
"debug.notification.interruptiveness", false);
@@ -4080,6 +4084,8 @@ public class NotificationManagerService extends SystemService {
try {
if (filter.stats) {
dumpJson(pw, filter);
+ } else if (filter.rvStats) {
+ dumpRemoteViewStats(pw, filter);
} else if (filter.proto) {
dumpProto(fd, filter);
} else if (filter.criticalPriority) {
@@ -4556,6 +4562,49 @@ public class NotificationManagerService extends SystemService {
new NotificationShellCmd(NotificationManagerService.this)
.exec(this, in, out, err, args, callback, resultReceiver);
}
+
+ /**
+ * Get stats committed after startNs
+ *
+ * @param startNs Report stats committed after this time in nanoseconds.
+ * @param report Indicatess which section to include in the stats.
+ * @param doAgg Whether to aggregate the stats or keep them separated.
+ * @param out List of protos of individual commits or one representing the
+ * aggregate.
+ * @return the report time in nanoseconds, or 0 on error.
+ */
+ @Override
+ public long pullStats(long startNs, int report, boolean doAgg,
+ List<ParcelFileDescriptor> out) {
+ checkCallerIsSystemOrShell();
+ long startMs = TimeUnit.MILLISECONDS.convert(startNs, TimeUnit.NANOSECONDS);
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ switch (report) {
+ case REPORT_REMOTE_VIEWS:
+ Slog.e(TAG, "pullStats REPORT_REMOTE_VIEWS from: "
+ + startMs + " wtih " + doAgg);
+ PulledStats stats = mUsageStats.remoteViewStats(startMs, doAgg);
+ if (stats != null) {
+ out.add(stats.toParcelFileDescriptor(report));
+ Slog.e(TAG, "exiting pullStats with: " + out.size());
+ long endNs = TimeUnit.NANOSECONDS
+ .convert(stats.endTimeMs(), TimeUnit.MILLISECONDS);
+ return endNs;
+ }
+ Slog.e(TAG, "null stats for: " + report);
+ }
+ } catch (IOException e) {
+
+ Slog.e(TAG, "exiting pullStats: on error", e);
+ return 0;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ Slog.e(TAG, "exiting pullStats: bad request");
+ return 0;
+ }
};
@VisibleForTesting
@@ -4773,6 +4822,15 @@ public class NotificationManagerService extends SystemService {
pw.println(dump);
}
+ private void dumpRemoteViewStats(PrintWriter pw, @NonNull DumpFilter filter) {
+ PulledStats stats = mUsageStats.remoteViewStats(filter.since, true);
+ if (stats == null) {
+ pw.println("no remote view stats reported.");
+ return;
+ }
+ stats.dump(REPORT_REMOTE_VIEWS, pw, filter);
+ }
+
private void dumpProto(FileDescriptor fd, @NonNull DumpFilter filter) {
final ProtoOutputStream proto = new ProtoOutputStream(fd);
synchronized (mNotificationLock) {
@@ -9084,6 +9142,7 @@ public class NotificationManagerService extends SystemService {
public boolean zen;
public long since;
public boolean stats;
+ public boolean rvStats;
public boolean redact = true;
public boolean proto = false;
public boolean criticalPriority = false;
@@ -9119,6 +9178,14 @@ public class NotificationManagerService extends SystemService {
} else {
filter.since = 0;
}
+ } else if ("--remote-view-stats".equals(a)) {
+ filter.rvStats = true;
+ if (ai < args.length-1) {
+ ai++;
+ filter.since = Long.parseLong(args[ai]);
+ } else {
+ filter.since = 0;
+ }
} else if (PRIORITY_ARG.equals(a)) {
// Bugreport will call the service twice with priority arguments, first to dump
// critical sections and then non critical ones. Set approriate filters
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index fe3d0eb3e469..ac8d1a9a9ad4 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -149,6 +149,7 @@ public class NotificationUsageStats {
stats.numPostedByApp++;
stats.updateInterarrivalEstimate(now);
stats.countApiUse(notification);
+ stats.numUndecoratedRemoteViews += (isUndecoratedRemoteView(notification) ? 1 : 0);
}
releaseAggregatedStatsLocked(aggregatedStatsArray);
if (ENABLE_SQLITE_LOG) {
@@ -157,6 +158,13 @@ public class NotificationUsageStats {
}
/**
+ * Does this notification use RemoveViews without a platform decoration?
+ */
+ protected static boolean isUndecoratedRemoteView(NotificationRecord notification) {
+ return (notification.getNotification().getNotificationStyle() == null);
+ }
+
+ /**
* Called when a notification has been updated.
*/
public synchronized void registerUpdatedByApp(NotificationRecord notification,
@@ -337,6 +345,15 @@ public class NotificationUsageStats {
return dump;
}
+ public PulledStats remoteViewStats(long startMs, boolean aggregate) {
+ if (ENABLE_SQLITE_LOG) {
+ if (aggregate) {
+ return mSQLiteLog.remoteViewAggStats(startMs);
+ }
+ }
+ return null;
+ }
+
public synchronized void dump(PrintWriter pw, String indent, DumpFilter filter) {
if (ENABLE_AGGREGATED_IN_MEMORY_STATS) {
for (AggregatedStats as : mStats.values()) {
@@ -414,6 +431,7 @@ public class NotificationUsageStats {
public int numRateViolations;
public int numAlertViolations;
public int numQuotaViolations;
+ public int numUndecoratedRemoteViews;
public long mLastAccessTime;
public int numImagesRemoved;
@@ -685,6 +703,8 @@ public class NotificationUsageStats {
output.append(indentPlusTwo).append(noisyImportance.toString()).append("\n");
output.append(indentPlusTwo).append(quietImportance.toString()).append("\n");
output.append(indentPlusTwo).append(finalImportance.toString()).append("\n");
+ output.append(indentPlusTwo);
+ output.append("numUndecorateRVs=").append(numUndecoratedRemoteViews).append("\n");
output.append(indent).append("}");
return output.toString();
}
@@ -1044,7 +1064,7 @@ public class NotificationUsageStats {
private static final int MSG_DISMISS = 4;
private static final String DB_NAME = "notification_log.db";
- private static final int DB_VERSION = 5;
+ private static final int DB_VERSION = 7;
/** Age in ms after which events are pruned from the DB. */
private static final long HORIZON_MS = 7 * 24 * 60 * 60 * 1000L; // 1 week
@@ -1077,6 +1097,7 @@ public class NotificationUsageStats {
private static final String COL_FIRST_EXPANSIONTIME_MS = "first_expansion_time_ms";
private static final String COL_AIRTIME_EXPANDED_MS = "expansion_airtime_ms";
private static final String COL_EXPAND_COUNT = "expansion_count";
+ private static final String COL_UNDECORATED = "undecorated";
private static final int EVENT_TYPE_POST = 1;
@@ -1102,12 +1123,20 @@ public class NotificationUsageStats {
"COUNT(*) AS cnt, " +
"SUM(" + COL_MUTED + ") as muted, " +
"SUM(" + COL_NOISY + ") as noisy, " +
- "SUM(" + COL_DEMOTED + ") as demoted " +
+ "SUM(" + COL_DEMOTED + ") as demoted, " +
+ "SUM(" + COL_UNDECORATED + ") as undecorated " +
"FROM " + TAB_LOG + " " +
"WHERE " +
COL_EVENT_TYPE + "=" + EVENT_TYPE_POST +
" AND " + COL_EVENT_TIME + " > %d " +
" GROUP BY " + COL_EVENT_USER_ID + ", day, " + COL_PKG;
+ private static final String UNDECORATED_QUERY = "SELECT " +
+ COL_PKG + ", " +
+ "MAX(" + COL_EVENT_TIME + ") as max_time " +
+ "FROM " + TAB_LOG + " " +
+ "WHERE " + COL_UNDECORATED + "> 0 " +
+ " AND " + COL_EVENT_TIME + " > %d " +
+ "GROUP BY " + COL_PKG;
public SQLiteLog(Context context) {
HandlerThread backgroundThread = new HandlerThread("notification-sqlite-log",
@@ -1163,7 +1192,8 @@ public class NotificationUsageStats {
COL_AIRTIME_MS + " INT," +
COL_FIRST_EXPANSIONTIME_MS + " INT," +
COL_AIRTIME_EXPANDED_MS + " INT," +
- COL_EXPAND_COUNT + " INT" +
+ COL_EXPAND_COUNT + " INT," +
+ COL_UNDECORATED + " INT" +
")");
}
@@ -1273,6 +1303,7 @@ public class NotificationUsageStats {
} else {
putPosttimeVisibility(r, cv);
}
+ cv.put(COL_UNDECORATED, (isUndecoratedRemoteView(r) ? 1 : 0));
SQLiteDatabase db = mHelper.getWritableDatabase();
if (db.insert(TAB_LOG, null, cv) < 0) {
Log.wtf(TAG, "Error while trying to insert values: " + cv);
@@ -1353,5 +1384,22 @@ public class NotificationUsageStats {
}
return dump;
}
+
+ public PulledStats remoteViewAggStats(long startMs) {
+ PulledStats stats = new PulledStats(startMs);
+ SQLiteDatabase db = mHelper.getReadableDatabase();
+ String q = String.format(UNDECORATED_QUERY, startMs);
+ Cursor cursor = db.rawQuery(q, null);
+ try {
+ for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
+ String pkg = cursor.getString(0);
+ long maxTimeMs = cursor.getLong(1);
+ stats.addUndecoratedPackage(pkg, maxTimeMs);
+ }
+ } finally {
+ cursor.close();
+ }
+ return stats;
+ }
}
}
diff --git a/services/core/java/com/android/server/notification/PulledStats.java b/services/core/java/com/android/server/notification/PulledStats.java
new file mode 100644
index 000000000000..ada890a10361
--- /dev/null
+++ b/services/core/java/com/android/server/notification/PulledStats.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.notification;
+
+import static com.android.server.notification.NotificationManagerService.REPORT_REMOTE_VIEWS;
+
+import android.os.ParcelFileDescriptor;
+import android.service.notification.NotificationRemoteViewsProto;
+import android.service.notification.PackageRemoteViewInfoProto;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PulledStats {
+ static final String TAG = "PulledStats";
+
+ private final long mTimePeriodStartMs;
+ private long mTimePeriodEndMs;
+ private List<String> mUndecoratedPackageNames;
+
+ public PulledStats(long startMs) {
+ mTimePeriodEndMs = mTimePeriodStartMs = startMs;
+ mUndecoratedPackageNames = new ArrayList<>();
+ }
+
+ ParcelFileDescriptor toParcelFileDescriptor(int report)
+ throws IOException {
+ final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
+ switch(report) {
+ case REPORT_REMOTE_VIEWS:
+ Thread thr = new Thread("NotificationManager pulled metric output") {
+ public void run() {
+ try {
+ FileOutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(
+ fds[1]);
+ final ProtoOutputStream proto = new ProtoOutputStream(fout);
+ writeToProto(report, proto);
+ proto.flush();
+ fout.close();
+ } catch (IOException e) {
+ Slog.w(TAG, "Failure writing pipe", e);
+ }
+ }
+ };
+ thr.start();
+ break;
+
+ default:
+ Slog.w(TAG, "Unknown pulled stats request: " + report);
+ break;
+ }
+ return fds[0];
+ }
+
+ /*
+ * @return the most recent timestamp in the report, as nanoseconds.
+ */
+ public long endTimeMs() {
+ return mTimePeriodEndMs;
+ }
+
+ public void dump(int report, PrintWriter pw, NotificationManagerService.DumpFilter filter) {
+ switch(report) {
+ case REPORT_REMOTE_VIEWS:
+ pw.print(" Packages with undecordated notifications (");
+ pw.print(mTimePeriodStartMs);
+ pw.print(" - ");
+ pw.print(mTimePeriodEndMs);
+ pw.println("):");
+ if (mUndecoratedPackageNames.size() == 0) {
+ pw.println(" none");
+ } else {
+ for (String pkg : mUndecoratedPackageNames) {
+ if (!filter.filtered || pkg.equals(filter.pkgFilter)) {
+ pw.println(" " + pkg);
+ }
+ }
+ }
+ break;
+
+ default:
+ pw.println("Unknown pulled stats request: " + report);
+ break;
+ }
+ }
+
+ @VisibleForTesting
+ void writeToProto(int report, ProtoOutputStream proto) {
+ switch(report) {
+ case REPORT_REMOTE_VIEWS:
+ for (String pkg: mUndecoratedPackageNames) {
+ long token = proto.start(NotificationRemoteViewsProto.PACKAGE_REMOTE_VIEW_INFO);
+ proto.write(PackageRemoteViewInfoProto.PACKAGE_NAME, pkg);
+ proto.end(token);
+ }
+ break;
+
+ default:
+ Slog.w(TAG, "Unknown pulled stats request: " + report);
+ break;
+ }
+ }
+
+ public void addUndecoratedPackage(String packageName, long timestampMs) {
+ mUndecoratedPackageNames.add(packageName);
+ mTimePeriodEndMs = Math.max(mTimePeriodEndMs, timestampMs);
+ }
+}
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 1222d9a29baf..2b4b409f329a 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -36,6 +36,7 @@ import android.os.Environment;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.sysprop.ApexProperties;
+import android.util.Singleton;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
@@ -65,22 +66,31 @@ abstract class ApexManager {
static final int MATCH_ACTIVE_PACKAGE = 1 << 0;
static final int MATCH_FACTORY_PACKAGE = 1 << 1;
+ private static final Singleton<ApexManager> sApexManagerSingleton =
+ new Singleton<ApexManager>() {
+ @Override
+ protected ApexManager create() {
+ if (ApexProperties.updatable().orElse(false)) {
+ try {
+ return new ApexManagerImpl(IApexService.Stub.asInterface(
+ ServiceManager.getServiceOrThrow("apexservice")));
+ } catch (ServiceManager.ServiceNotFoundException e) {
+ throw new IllegalStateException(
+ "Required service apexservice not available");
+ }
+ } else {
+ return new ApexManagerFlattenedApex();
+ }
+ }
+ };
+
/**
* Returns an instance of either {@link ApexManagerImpl} or {@link ApexManagerFlattenedApex}
* depending on whether this device supports APEX, i.e. {@link ApexProperties#updatable()}
* evaluates to {@code true}.
*/
- static ApexManager create(Context systemContext) {
- if (ApexProperties.updatable().orElse(false)) {
- try {
- return new ApexManagerImpl(systemContext, IApexService.Stub.asInterface(
- ServiceManager.getServiceOrThrow("apexservice")));
- } catch (ServiceManager.ServiceNotFoundException e) {
- throw new IllegalStateException("Required service apexservice not available");
- }
- } else {
- return new ApexManagerFlattenedApex();
- }
+ static ApexManager getInstance() {
+ return sApexManagerSingleton.get();
}
/**
@@ -101,7 +111,7 @@ abstract class ApexManager {
*/
abstract List<ActiveApexInfo> getActiveApexInfos();
- abstract void systemReady();
+ abstract void systemReady(Context context);
/**
* Retrieves information about an APEX package.
@@ -248,7 +258,6 @@ abstract class ApexManager {
@VisibleForTesting
static class ApexManagerImpl extends ApexManager {
private final IApexService mApexService;
- private final Context mContext;
private final Object mLock = new Object();
/**
* A map from {@code APEX packageName} to the {@Link PackageInfo} generated from the {@code
@@ -260,8 +269,7 @@ abstract class ApexManager {
@GuardedBy("mLock")
private List<PackageInfo> mAllPackagesCache;
- ApexManagerImpl(Context context, IApexService apexService) {
- mContext = context;
+ ApexManagerImpl(IApexService apexService) {
mApexService = apexService;
}
@@ -302,14 +310,14 @@ abstract class ApexManager {
}
@Override
- void systemReady() {
- mContext.registerReceiver(new BroadcastReceiver() {
+ void systemReady(Context context) {
+ context.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Post populateAllPackagesCacheIfNeeded to a background thread, since it's
// expensive to run it in broadcast handler thread.
BackgroundThread.getHandler().post(() -> populateAllPackagesCacheIfNeeded());
- mContext.unregisterReceiver(this);
+ context.unregisterReceiver(this);
}
}, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
}
@@ -643,7 +651,7 @@ abstract class ApexManager {
}
@Override
- void systemReady() {
+ void systemReady(Context context) {
// No-op
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3d4247e761b5..fcaf5e1d912a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2605,7 +2605,7 @@ public class PackageManagerService extends IPackageManager.Stub
mProtectedPackages = new ProtectedPackages(mContext);
- mApexManager = ApexManager.create(mContext);
+ mApexManager = ApexManager.getInstance();
mAppsFilter = mInjector.getAppsFilter();
mDirsToScanAsSystem = new ArrayList<>();
@@ -20371,7 +20371,7 @@ public class PackageManagerService extends IPackageManager.Stub
storage.registerListener(mStorageListener);
mInstallerService.systemReady();
- mApexManager.systemReady();
+ mApexManager.systemReady(mContext);
mPackageDexOptimizer.systemReady();
mInjector.getStorageManagerInternal().addExternalStoragePolicy(
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 83891f60d4f7..a62616623cb5 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -16,6 +16,13 @@
package com.android.server.rollback;
+import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH;
+import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING;
+import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_EXPLICIT_HEALTH_CHECK;
+import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH;
+import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN;
+
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -41,6 +48,7 @@ import android.util.StatsLog;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.server.PackageWatchdog;
+import com.android.server.PackageWatchdog.FailureReasons;
import com.android.server.PackageWatchdog.PackageHealthObserver;
import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
@@ -106,10 +114,11 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
}
@Override
- public boolean execute(VersionedPackage failedPackage) {
+ public boolean execute(VersionedPackage failedPackage, @FailureReasons int rollbackReason) {
RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
VersionedPackage moduleMetadataPackage = getModuleMetadataPackage();
RollbackInfo rollback = getAvailableRollback(rollbackManager, failedPackage);
+ int reasonToLog = mapFailureReasonToMetric(rollbackReason);
if (rollback == null) {
Slog.w(TAG, "Expected rollback but no valid rollback found for package: [ "
@@ -119,7 +128,8 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
}
logEvent(moduleMetadataPackage,
- StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE);
+ StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE,
+ reasonToLog, failedPackage.getPackageName());
LocalIntentReceiver rollbackReceiver = new LocalIntentReceiver((Intent result) -> {
int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
RollbackManager.STATUS_FAILURE);
@@ -136,11 +146,13 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
moduleMetadataPackage);
} else {
logEvent(moduleMetadataPackage,
- StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS);
+ StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
+ reasonToLog, failedPackage.getPackageName());
}
} else {
logEvent(moduleMetadataPackage,
- StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE);
+ StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
+ reasonToLog, failedPackage.getPackageName());
}
});
@@ -219,12 +231,14 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
}
if (sessionInfo.isStagedSessionApplied()) {
logEvent(oldModuleMetadataPackage,
- StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS);
+ StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
+ WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, "");
} else if (sessionInfo.isStagedSessionReady()) {
// TODO: What do for staged session ready but not applied
} else {
logEvent(oldModuleMetadataPackage,
- StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE);
+ StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
+ WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, "");
}
}
@@ -303,12 +317,16 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
saveLastStagedRollbackId(rollbackId);
logEvent(moduleMetadataPackage,
StatsLog
- .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_BOOT_TRIGGERED);
+ .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_BOOT_TRIGGERED,
+ WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN,
+ "");
mContext.getSystemService(PowerManager.class).reboot("Rollback staged install");
} else if (sessionInfo.isStagedSessionFailed()
&& markStagedSessionHandled(rollbackId)) {
logEvent(moduleMetadataPackage,
- StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE);
+ StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
+ WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN,
+ "");
mContext.unregisterReceiver(listener);
}
}
@@ -355,11 +373,12 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
return rollbackId;
}
- private static void logEvent(@Nullable VersionedPackage moduleMetadataPackage, int type) {
+ private static void logEvent(@Nullable VersionedPackage moduleMetadataPackage, int type,
+ int rollbackReason, @NonNull String failingPackageName) {
Slog.i(TAG, "Watchdog event occurred of type: " + type);
if (moduleMetadataPackage != null) {
StatsLog.logWatchdogRollbackOccurred(type, moduleMetadataPackage.getPackageName(),
- moduleMetadataPackage.getVersionCode());
+ moduleMetadataPackage.getVersionCode(), rollbackReason, failingPackageName);
}
}
@@ -371,7 +390,7 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
mNumberOfNativeCrashPollsRemaining--;
// Check if native watchdog reported a crash
if ("1".equals(SystemProperties.get("sys.init.updatable_crashing"))) {
- execute(getModuleMetadataPackage());
+ execute(getModuleMetadataPackage(), PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
// we stop polling after an attempt to execute rollback, regardless of whether the
// attempt succeeds or not
} else {
@@ -392,4 +411,20 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
+ "and mitigate native crashes");
mHandler.post(()->checkAndMitigateNativeCrashes());
}
+
+ private int mapFailureReasonToMetric(@FailureReasons int failureReason) {
+ switch (failureReason) {
+ case PackageWatchdog.FAILURE_REASON_NATIVE_CRASH:
+ return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH;
+ case PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK:
+ return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_EXPLICIT_HEALTH_CHECK;
+ case PackageWatchdog.FAILURE_REASON_APP_CRASH:
+ return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH;
+ case PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING:
+ return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING;
+ default:
+ return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN;
+ }
+ }
+
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 5d796055dcc7..83c854bae4b5 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -620,10 +620,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// TODO: Make this final
int mTargetSdk;
- // Set to true when this app creates a surface while in the middle of an animation. In that
- // case do not clear allDrawn until the animation completes.
- boolean deferClearAllDrawn;
-
// Is this window's surface needed? This is almost like visible, except
// it will sometimes be true a little earlier: when the activity record has
// been shown, but is still waiting for its app transition to execute
@@ -771,10 +767,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
pw.print(" primaryColor=");
pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
pw.print(prefix + " backgroundColor=");
- pw.println(Integer.toHexString(taskDescription.getBackgroundColor()));
- pw.print(prefix + " statusBarColor=");
- pw.println(Integer.toHexString(taskDescription.getStatusBarColor()));
- pw.print(prefix + " navigationBarColor=");
+ pw.print(Integer.toHexString(taskDescription.getBackgroundColor()));
+ pw.print(" statusBarColor=");
+ pw.print(Integer.toHexString(taskDescription.getStatusBarColor()));
+ pw.print(" navigationBarColor=");
pw.println(Integer.toHexString(taskDescription.getNavigationBarColor()));
}
}
@@ -847,14 +843,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
pw.println(requestedVrComponent);
}
super.dump(pw, prefix, dumpAll);
- pw.print(" visible="); pw.print(mVisible);
- if (appToken != null) {
- pw.println(prefix + "app=true mVoiceInteraction=" + mVoiceInteraction);
+ if (mVoiceInteraction) {
+ pw.println(prefix + "mVoiceInteraction=true");
}
- pw.print(prefix); pw.print(" mOccludesParent="); pw.print(mOccludesParent);
+ pw.print(prefix); pw.print("mOccludesParent="); pw.print(mOccludesParent);
pw.print(" mOrientation="); pw.println(mOrientation);
pw.println(prefix + "mVisibleRequested=" + mVisibleRequested
- + " mClientVisible=" + mClientVisible
+ + " mVisible=" + mVisible + " mClientVisible=" + mClientVisible
+ ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
+ " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
if (paused) {
@@ -901,7 +896,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
}
if (lastVisibleTime != 0 || nowVisible) {
- pw.print(prefix); pw.print(" nowVisible="); pw.print(nowVisible);
+ pw.print(prefix); pw.print("nowVisible="); pw.print(nowVisible);
pw.print(" lastVisibleTime=");
if (lastVisibleTime == 0) pw.print("0");
else TimeUtils.formatDuration(lastVisibleTime, now, pw);
@@ -3235,7 +3230,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// to move that animation to the new one.
if (fromActivity.allDrawn) {
allDrawn = true;
- deferClearAllDrawn = fromActivity.deferClearAllDrawn;
}
if (fromActivity.firstWindowDrawn) {
firstWindowDrawn = true;
@@ -3719,7 +3713,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
void clearAllDrawn() {
allDrawn = false;
- deferClearAllDrawn = false;
}
/**
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index e9ad0d361b07..d7f4b34ba56d 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -389,7 +389,6 @@ public class AppTransitionController {
// this guy's animations regardless of whether it's
// gotten drawn.
wtoken.allDrawn = true;
- wtoken.deferClearAllDrawn = false;
// Ensure that apps that are mid-starting are also scheduled to have their
// starting windows removed after the animation is complete
if (wtoken.startingWindow != null && !wtoken.startingWindow.mAnimatingExit) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index c42029155bd0..175fccbdd0ba 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -439,10 +439,6 @@ class WindowStateAnimator {
if (!mWin.mActivityRecord.isAnimating(TRANSITION)) {
mWin.mActivityRecord.clearAllDrawn();
- } else {
- // Currently animating, persist current state of allDrawn until animation
- // is complete.
- mWin.mActivityRecord.deferClearAllDrawn = true;
}
}
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index f81713ed4385..53edf9d3086a 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -280,10 +280,11 @@ class WindowToken extends WindowContainer<WindowState> {
super.dump(pw, prefix, dumpAll);
pw.print(prefix); pw.print("windows="); pw.println(mChildren);
pw.print(prefix); pw.print("windowType="); pw.print(windowType);
- pw.print(" hasVisible="); pw.println(hasVisible);
+ pw.print(" hasVisible="); pw.print(hasVisible);
if (waitingToShow) {
- pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
+ pw.print(" waitingToShow=true");
}
+ pw.println();
}
@Override
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index cb599be82aa6..ee0449d95e00 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4345,6 +4345,40 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
+ /**
+ * Get the list of active admins for an affected user:
+ * <ul>
+ * <li>The active admins associated with the userHandle itself</li>
+ * <li>The parent active admins for each managed profile associated with the userHandle</li>
+ * </ul>
+ *
+ * @param userHandle the affected user for whom to get the active admins
+ * @param parent whether the parent active admins should be included in the list of active
+ * admins or not
+ * @return the list of active admins for the affected user
+ */
+ private List<ActiveAdmin> getActiveAdminsForAffectedUser(int userHandle, boolean parent) {
+ if (!parent) {
+ return getUserDataUnchecked(userHandle).mAdminList;
+ }
+ ArrayList<ActiveAdmin> admins = new ArrayList<>();
+ for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
+ DevicePolicyData policy = getUserData(userInfo.id);
+ if (!userInfo.isManagedProfile()) {
+ admins.addAll(policy.mAdminList);
+ } else {
+ // For managed profiles, policies set on the parent profile will be included
+ for (int i = 0; i < policy.mAdminList.size(); i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (admin.hasParentActiveAdmin()) {
+ admins.add(admin.getParentActiveAdmin());
+ }
+ }
+ }
+ }
+ return admins;
+ }
+
private boolean isSeparateProfileChallengeEnabled(int userHandle) {
long ident = mInjector.binderClearCallingIdentity();
try {
@@ -5096,118 +5130,58 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
- private boolean canPOorDOCallResetPassword(ActiveAdmin admin, @UserIdInt int userId) {
- // Only if the admins targets a pre-O SDK
- return getTargetSdk(admin.info.getPackageName(), userId) < Build.VERSION_CODES.O;
- }
-
- /* PO or DO could do an untrusted reset in certain conditions. */
- private boolean canUserHaveUntrustedCredentialReset(@UserIdInt int userId) {
- synchronized (getLockObject()) {
- // An active DO or PO might be able to fo an untrusted credential reset
- for (final ActiveAdmin admin : getUserData(userId).mAdminList) {
- if (!isActiveAdminWithPolicyForUserLocked(admin,
- DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, userId)) {
- continue;
- }
- if (canPOorDOCallResetPassword(admin, userId)) {
- return true;
- }
- }
- return false;
+ private boolean setPasswordPrivileged(@NonNull String password, int flags, int callingUid) {
+ // Only allow setting password on an unsecured user
+ if (isLockScreenSecureUnchecked(UserHandle.getUserId(callingUid))) {
+ throw new SecurityException("Cannot change current password");
}
+ return resetPasswordInternal(password, 0, null, flags, callingUid);
}
+
@Override
- public boolean resetPassword(String passwordOrNull, int flags) throws RemoteException {
+ public boolean resetPassword(@Nullable String password, int flags) throws RemoteException {
if (!mLockPatternUtils.hasSecureLockScreen()) {
Slog.w(LOG_TAG, "Cannot reset password when the device has no lock screen");
return false;
}
-
+ if (password == null) password = "";
final int callingUid = mInjector.binderGetCallingUid();
final int userHandle = mInjector.userHandleGetCallingUserId();
- String password = passwordOrNull != null ? passwordOrNull : "";
-
- // Password resetting to empty/null is not allowed for managed profiles.
- if (TextUtils.isEmpty(password)) {
- enforceNotManagedProfile(userHandle, "clear the active password");
+ // As of R, only privlleged caller holding RESET_PASSWORD can call resetPassword() to
+ // set password to an unsecured user.
+ if (mContext.checkCallingPermission(permission.RESET_PASSWORD)
+ == PackageManager.PERMISSION_GRANTED) {
+ return setPasswordPrivileged(password, flags, callingUid);
}
synchronized (getLockObject()) {
- // If caller has PO (or DO) it can change the password, so see if that's the case first.
+ // If caller has PO (or DO) throw or fail silently depending on its target SDK level.
ActiveAdmin admin = getActiveAdminWithPolicyForUidLocked(
null, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, callingUid);
- final boolean preN;
if (admin != null) {
- if (!canPOorDOCallResetPassword(admin, userHandle)) {
- throw new SecurityException("resetPassword() is deprecated for DPC targeting O"
- + " or later");
- }
- preN = getTargetSdk(admin.info.getPackageName(),
- userHandle) <= android.os.Build.VERSION_CODES.M;
- } else {
- // Otherwise, make sure the caller has any active admin with the right policy or
- // the required permission.
- admin = getActiveAdminOrCheckPermissionForCallerLocked(
- null,
- DeviceAdminInfo.USES_POLICY_RESET_PASSWORD,
- android.Manifest.permission.RESET_PASSWORD);
- // Cannot be preN if admin is null because an exception would have been
- // thrown before getting here
- preN = admin == null ? false : getTargetSdk(admin.info.getPackageName(),
- userHandle) <= android.os.Build.VERSION_CODES.M;
-
- // As of N, password resetting to empty/null is not allowed anymore.
- // TODO Should we allow DO/PO to set an empty password?
- if (TextUtils.isEmpty(password)) {
- if (!preN) {
- throw new SecurityException("Cannot call with null password");
- } else {
- Slog.e(LOG_TAG, "Cannot call with null password");
- return false;
- }
- }
- // As of N, password cannot be changed by the admin if it is already set.
- if (isLockScreenSecureUnchecked(userHandle)) {
- if (!preN) {
- throw new SecurityException("Cannot change current password");
- } else {
- Slog.e(LOG_TAG, "Cannot change current password");
- return false;
- }
- }
- }
- // Do not allow to reset password when current user has a managed profile
- if (!isManagedProfile(userHandle)) {
- for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
- if (userInfo.isManagedProfile()) {
- if (!preN) {
- throw new IllegalStateException(
- "Cannot reset password on user has managed profile");
- } else {
- Slog.e(LOG_TAG, "Cannot reset password on user has managed profile");
- return false;
- }
- }
- }
- }
- // Do not allow to reset password when user is locked
- if (!mUserManager.isUserUnlocked(userHandle)) {
- if (!preN) {
- throw new IllegalStateException("Cannot reset password when user is locked");
- } else {
- Slog.e(LOG_TAG, "Cannot reset password when user is locked");
+ if (getTargetSdk(admin.info.getPackageName(), userHandle) < Build.VERSION_CODES.O) {
+ Slog.e(LOG_TAG, "DPC can no longer call resetPassword()");
return false;
}
+ throw new SecurityException("Device admin can no longer call resetPassword()");
}
- }
- return resetPasswordInternal(password, 0, null, flags, callingUid, userHandle);
+ // Legacy device admin cannot call resetPassword either
+ admin = getActiveAdminForCallerLocked(
+ null, DeviceAdminInfo.USES_POLICY_RESET_PASSWORD, false);
+ if (getTargetSdk(admin.info.getPackageName(),
+ userHandle) <= android.os.Build.VERSION_CODES.M) {
+ Slog.e(LOG_TAG, "Device admin can no longer call resetPassword()");
+ return false;
+ }
+ throw new SecurityException("Device admin can no longer call resetPassword()");
+ }
}
private boolean resetPasswordInternal(String password, long tokenHandle, byte[] token,
- int flags, int callingUid, int userHandle) {
+ int flags, int callingUid) {
+ final int userHandle = UserHandle.getUserId(callingUid);
synchronized (getLockObject()) {
final PasswordMetrics minMetrics = getPasswordMinimumMetrics(userHandle);
final List<PasswordValidationError> validationErrors;
@@ -5245,21 +5219,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// Don't do this with the lock held, because it is going to call
// back in to the service.
final long ident = mInjector.binderClearCallingIdentity();
- final boolean result;
final LockscreenCredential newCredential =
LockscreenCredential.createPasswordOrNone(password);
try {
- if (token == null) {
- // This is the legacy reset password for DPM. Here we want to be able to override
- // the old device password without necessarily knowing it.
- mLockPatternUtils.setLockCredential(
- newCredential,
- LockscreenCredential.createNone(),
- userHandle, /*allowUntrustedChange */true);
- result = true;
+ if (tokenHandle == 0 || token == null) {
+ if (!mLockPatternUtils.setLockCredential(newCredential,
+ LockscreenCredential.createNone(), userHandle)) {
+ return false;
+ }
} else {
- result = mLockPatternUtils.setLockCredentialWithToken(newCredential, tokenHandle,
- token, userHandle);
+ if (!mLockPatternUtils.setLockCredentialWithToken(newCredential, tokenHandle,
+ token, userHandle)) {
+ return false;
+ }
}
boolean requireEntry = (flags & DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0;
if (requireEntry) {
@@ -5276,7 +5248,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
- return result;
+ return true;
}
private boolean isLockScreenSecureUnchecked(int userId) {
@@ -7769,22 +7741,25 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
* Disables all device cameras according to the specified admin.
*/
@Override
- public void setCameraDisabled(ComponentName who, boolean disabled) {
+ public void setCameraDisabled(ComponentName who, boolean disabled, boolean parent) {
if (!mHasFeature) {
return;
}
Preconditions.checkNotNull(who, "ComponentName is null");
- final int userHandle = mInjector.userHandleGetCallingUserId();
+ int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
- DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA);
+ DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA, parent);
+ if (parent) {
+ enforceProfileOwnerOfOrganizationOwnedDevice(ap);
+ }
if (ap.disableCamera != disabled) {
ap.disableCamera = disabled;
saveSettingsLocked(userHandle);
}
}
// Tell the user manager that the restrictions have changed.
- pushUserRestrictions(userHandle);
+ pushUserRestrictions(parent ? getProfileParentId(userHandle) : userHandle);
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_CAMERA_DISABLED)
.setAdmin(who)
@@ -7797,18 +7772,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
* active admins.
*/
@Override
- public boolean getCameraDisabled(ComponentName who, int userHandle) {
- return getCameraDisabled(who, userHandle, /* mergeDeviceOwnerRestriction= */ true);
+ public boolean getCameraDisabled(ComponentName who, int userHandle, boolean parent) {
+ return getCameraDisabled(who, userHandle, /* mergeDeviceOwnerRestriction= */ true, parent);
}
private boolean getCameraDisabled(ComponentName who, int userHandle,
- boolean mergeDeviceOwnerRestriction) {
+ boolean mergeDeviceOwnerRestriction, boolean parent) {
if (!mHasFeature) {
return false;
}
+ if (parent) {
+ ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA, parent);
+ enforceProfileOwnerOfOrganizationOwnedDevice(ap);
+ }
synchronized (getLockObject()) {
if (who != null) {
- ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent);
return (admin != null) ? admin.disableCamera : false;
}
// First, see if DO has set it. If so, it's device-wide.
@@ -7818,13 +7798,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return true;
}
}
-
- // Then check each device admin on the user.
- DevicePolicyData policy = getUserData(userHandle);
+ // Return the strictest policy across all participating admins.
+ List<ActiveAdmin> admins = getActiveAdminsForAffectedUser(userHandle, parent);
// Determine whether or not the device camera is disabled for any active admins.
- final int N = policy.mAdminList.size();
- for (int i = 0; i < N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
+ for (ActiveAdmin admin: admins) {
if (admin.disableCamera) {
return true;
}
@@ -8636,6 +8613,25 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return null;
}
+ @GuardedBy("getLockObject()")
+ ActiveAdmin getProfileOwnerOfOrganizationOwnedDeviceLocked(int userHandle) {
+ final long ident = mInjector.binderClearCallingIdentity();
+ try {
+ for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
+ if (userInfo.isManagedProfile()) {
+ if (getProfileOwner(userInfo.id) != null
+ && canProfileOwnerAccessDeviceIds(userInfo.id)) {
+ ComponentName who = getProfileOwner(userInfo.id);
+ return getActiveAdminUncheckedLocked(who, userInfo.id);
+ }
+ }
+ }
+ } finally {
+ mInjector.binderRestoreCallingIdentity(ident);
+ }
+ return null;
+ }
+
@Override
public String getProfileOwnerName(int userHandle) {
if (!mHasFeature) {
@@ -10323,7 +10319,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private void pushUserRestrictions(int userId) {
synchronized (getLockObject()) {
final boolean isDeviceOwner = mOwners.isDeviceOwnerUserId(userId);
- final Bundle userRestrictions;
+ Bundle userRestrictions = null;
final int restrictionOwnerType;
if (isDeviceOwner) {
@@ -10335,42 +10331,60 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
addOrRemoveDisableCameraRestriction(userRestrictions, deviceOwner);
restrictionOwnerType = UserManagerInternal.OWNER_TYPE_DEVICE_OWNER;
} else {
- final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId);
- userRestrictions = profileOwner != null ? profileOwner.userRestrictions : null;
- addOrRemoveDisableCameraRestriction(userRestrictions, userId);
+ final ActiveAdmin profileOwnerOfOrganizationOwnedDevice =
+ getProfileOwnerOfOrganizationOwnedDeviceLocked(userId);
- if (isProfileOwnerOfOrganizationOwnedDevice(profileOwner)) {
+ // If profile owner of an organization owned device, the restrictions will be
+ // pushed to the parent instance.
+ if (profileOwnerOfOrganizationOwnedDevice != null && !isManagedProfile(userId)) {
restrictionOwnerType =
UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE;
- } else if (profileOwner != null) {
- restrictionOwnerType = UserManagerInternal.OWNER_TYPE_PROFILE_OWNER;
+ final ActiveAdmin parent = profileOwnerOfOrganizationOwnedDevice
+ .getParentActiveAdmin();
+ userRestrictions = parent.userRestrictions;
+ userRestrictions = addOrRemoveDisableCameraRestriction(userRestrictions,
+ parent);
} else {
- restrictionOwnerType = UserManagerInternal.OWNER_TYPE_NO_OWNER;
+ final ActiveAdmin profileOwner = getProfileOwnerAdminLocked(userId);
+
+ if (profileOwner != null) {
+ userRestrictions = profileOwner.userRestrictions;
+ restrictionOwnerType = UserManagerInternal.OWNER_TYPE_PROFILE_OWNER;
+ } else {
+ restrictionOwnerType = UserManagerInternal.OWNER_TYPE_NO_OWNER;
+ }
+ userRestrictions = addOrRemoveDisableCameraRestriction(
+ userRestrictions, userId);
}
}
-
mUserManagerInternal.setDevicePolicyUserRestrictions(userId, userRestrictions,
restrictionOwnerType);
}
}
- private void addOrRemoveDisableCameraRestriction(Bundle userRestrictions, ActiveAdmin admin) {
- if (userRestrictions == null) return;
+ private Bundle addOrRemoveDisableCameraRestriction(Bundle userRestrictions, ActiveAdmin admin) {
+ if (userRestrictions == null) {
+ userRestrictions = new Bundle();
+ }
if (admin.disableCamera) {
userRestrictions.putBoolean(UserManager.DISALLOW_CAMERA, true);
} else {
userRestrictions.remove(UserManager.DISALLOW_CAMERA);
}
+ return userRestrictions;
}
- private void addOrRemoveDisableCameraRestriction(Bundle userRestrictions, int userId) {
- if (userRestrictions == null) return;
+ private Bundle addOrRemoveDisableCameraRestriction(Bundle userRestrictions, int userId) {
+ if (userRestrictions == null) {
+ userRestrictions = new Bundle();
+ }
if (getCameraDisabled(/* who= */ null, userId, /* mergeDeviceOwnerRestriction= */
false)) {
userRestrictions.putBoolean(UserManager.DISALLOW_CAMERA, true);
} else {
userRestrictions.remove(UserManager.DISALLOW_CAMERA);
}
+ return userRestrictions;
}
@Override
@@ -11673,11 +11687,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
- public boolean canUserHaveUntrustedCredentialReset(@UserIdInt int userId) {
- return DevicePolicyManagerService.this.canUserHaveUntrustedCredentialReset(userId);
- }
-
- @Override
public CharSequence getPrintingDisabledReasonForUser(@UserIdInt int userId) {
synchronized (getLockObject()) {
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_PRINTING,
@@ -13890,7 +13899,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (policy.mPasswordTokenHandle != 0) {
final String password = passwordOrNull != null ? passwordOrNull : "";
return resetPasswordInternal(password, policy.mPasswordTokenHandle, token,
- flags, mInjector.binderGetCallingUid(), userHandle);
+ flags, mInjector.binderGetCallingUid());
} else {
Slog.w(LOG_TAG, "No saved token handle");
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 7508343b7130..21cacd45dcb5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -448,10 +448,6 @@ public final class SystemServer {
// Mmmmmm... more memory!
VMRuntime.getRuntime().clearGrowthLimit();
- // The system server has to run all of the time, so it needs to be
- // as efficient as possible with its memory usage.
- VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
-
// Some devices rely on runtime fingerprint generation, so make sure
// we've defined it before booting further.
Build.ensureFingerprintProperty();
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
index c5fb0bde579f..5f1f3083361b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
@@ -23,7 +23,6 @@ import static org.mockito.Mockito.when;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
@@ -39,6 +38,9 @@ import java.util.Map;
import java.util.Set;
public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
+
+ private static final String USER_TYPE_EMPTY = "";
+
private DpmMockContext mContext;
@Override
@@ -52,9 +54,10 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
}
public void testMigration() throws Exception {
- final File user10dir = getServices().addUser(10, 0);
- final File user11dir = getServices().addUser(11, UserInfo.FLAG_MANAGED_PROFILE);
- getServices().addUser(12, 0);
+ final File user10dir = getServices().addUser(10, 0, USER_TYPE_EMPTY);
+ final File user11dir = getServices().addUser(11, 0,
+ UserManager.USER_TYPE_PROFILE_MANAGED);
+ getServices().addUser(12, 0, USER_TYPE_EMPTY);
setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
setUpPackageManagerForAdmin(admin2, UserHandle.getUid(10, 123));
@@ -273,7 +276,8 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
// Test setting default restrictions for managed profile.
public void testMigration3_managedProfileOwner() throws Exception {
// Create a managed profile user.
- final File user10dir = getServices().addUser(10, UserInfo.FLAG_MANAGED_PROFILE);
+ final File user10dir = getServices().addUser(10, 0,
+ UserManager.USER_TYPE_PROFILE_MANAGED);
// Profile owner package for managed profile user.
setUpPackageManagerForAdmin(admin1, UserHandle.getUid(10, 123));
// Set up fake UserManager to make it look like a managed profile.
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 06b8716c0926..43d8f927a57e 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -151,6 +151,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
private DpmMockContext mServiceContext;
private DpmMockContext mAdmin1Context;
public DevicePolicyManager dpm;
+ public DevicePolicyManager parentDpm;
public DevicePolicyManagerServiceTestable dpms;
/*
@@ -240,6 +241,9 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm = new DevicePolicyManagerTestable(mContext, dpms);
+ parentDpm = new DevicePolicyManagerTestable(mServiceContext, dpms,
+ /* parentInstance= */true);
+
mContext.binder.restoreCallingIdentity(ident);
}
@@ -269,7 +273,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
anyString(), any(UserHandle.class));
// Add the first secondary user.
- getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0);
+ getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
+ UserManager.USER_TYPE_FULL_SECONDARY);
}
private void setAsProfileOwner(ComponentName admin) {
@@ -330,7 +335,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
public void testLoadAdminData_noAdmins() throws Exception {
final int ANOTHER_USER_ID = 15;
- getServices().addUser(ANOTHER_USER_ID, 0);
+ getServices().addUser(ANOTHER_USER_ID, 0, "");
initializeDpms();
@@ -477,7 +482,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
final int ANOTHER_USER_ID = 100;
final int ANOTHER_ADMIN_UID = UserHandle.getUid(ANOTHER_USER_ID, 20456);
- getServices().addUser(ANOTHER_USER_ID, 0); // Add one more user.
+ getServices().addUser(ANOTHER_USER_ID, 0, ""); // Add one more user.
// Set up pacakge manager for the other user.
setUpPackageManagerForAdmin(admin2, ANOTHER_ADMIN_UID);
@@ -1343,7 +1348,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
final int ANOTHER_USER_ID = 100;
final int ANOTHER_ADMIN_UID = UserHandle.getUid(ANOTHER_USER_ID, 456);
- getServices().addUser(ANOTHER_USER_ID, 0); // Add one more user.
+ getServices().addUser(ANOTHER_USER_ID, 0, ""); // Add one more user.
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_USERS);
@@ -1961,35 +1966,30 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// TODO Make sure restrictions are written to the file.
}
+ // TODO: (b/138709470) test addUserRestriction as PO of an organization-owned device
public void testSetUserRestriction_asPoOfOrgOwnedDevice() throws Exception {
- setupProfileOwner();
+ final int MANAGED_PROFILE_USER_ID = DpmMockContext.CALLER_USER_HANDLE;
+ final int MANAGED_PROFILE_ADMIN_UID =
+ UserHandle.getUid(MANAGED_PROFILE_USER_ID, DpmMockContext.SYSTEM_UID);
+ mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- final long ident = mServiceContext.binder.clearCallingIdentity();
- configureContextForAccess(mServiceContext, true);
+ addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
+ configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE);
- mServiceContext.binder.callingUid =
- UserHandle.getUid(DpmMockContext.CALLER_USER_HANDLE,
- DpmMockContext.CALLER_MANAGED_PROVISIONING_UID);
- try {
- runAsCaller(mServiceContext, dpms, dpm -> {
- dpm.markProfileOwnerOnOrganizationOwnedDevice(admin1);
- });
- } finally {
- mServiceContext.binder.restoreCallingIdentity(ident);
- }
+ when(getServices().userManager.getProfileParent(MANAGED_PROFILE_USER_ID))
+ .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "user system", 0));
- dpm.addUserRestriction(admin1, UserManager.DISALLOW_CONFIG_DATE_TIME);
+ parentDpm.setCameraDisabled(admin1, true);
verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
- eq(DpmMockContext.CALLER_USER_HANDLE),
- MockUtils.checkUserRestrictions(UserManager.DISALLOW_CONFIG_DATE_TIME),
+ eq(UserHandle.USER_SYSTEM),
+ MockUtils.checkUserRestrictions(UserManager.DISALLOW_CAMERA),
eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE));
reset(getServices().userManagerInternal);
- dpm.setCameraDisabled(admin1, true);
+ parentDpm.setCameraDisabled(admin1, false);
verify(getServices().userManagerInternal).setDevicePolicyUserRestrictions(
- eq(DpmMockContext.CALLER_USER_HANDLE),
- MockUtils.checkUserRestrictions(UserManager.DISALLOW_CONFIG_DATE_TIME,
- UserManager.DISALLOW_CAMERA),
+ eq(UserHandle.USER_SYSTEM),
+ MockUtils.checkUserRestrictions(),
eq(UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE));
reset(getServices().userManagerInternal);
}
@@ -3861,7 +3861,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Add a secondary user, it should never talk with.
final int ANOTHER_USER_ID = 36;
- getServices().addUser(ANOTHER_USER_ID, 0);
+ getServices().addUser(ANOTHER_USER_ID, 0, UserManager.USER_TYPE_FULL_SECONDARY);
// Since the managed profile is not affiliated, they should not be allowed to talk to each
// other.
@@ -5206,8 +5206,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
public void testRevertProfileOwnership_adminAndProfileMigrated() throws Exception {
- getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, UserInfo.FLAG_MANAGED_PROFILE,
- UserHandle.USER_SYSTEM);
+ getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
+ UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
DpmTestUtils.writeInputStreamToFile(
getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
getProfileOwnerPoliciesFile());
@@ -5218,8 +5218,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
public void testRevertProfileOwnership_profileNotMigrated() throws Exception {
- getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, UserInfo.FLAG_MANAGED_PROFILE,
- UserHandle.USER_SYSTEM);
+ getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
+ UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
DpmTestUtils.writeInputStreamToFile(
getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
getProfileOwnerPoliciesFile());
@@ -5230,8 +5230,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
public void testRevertProfileOwnership_adminAndProfileNotMigrated() throws Exception {
- getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, UserInfo.FLAG_MANAGED_PROFILE,
- UserHandle.USER_SYSTEM);
+ getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
+ UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
DpmTestUtils.writeInputStreamToFile(
getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_not_migrated),
getProfileOwnerPoliciesFile());
@@ -5405,11 +5405,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mServiceContext.permissions.add(permission.REQUEST_PASSWORD_COMPLEXITY);
setAsProfileOwner(admin1);
- new DevicePolicyManagerTestable(
- mServiceContext,
- dpms,
- /* parentInstance= */ true)
- .getPasswordComplexity();
+ parentDpm.getPasswordComplexity();
assertEquals(PASSWORD_COMPLEXITY_NONE, dpm.getPasswordComplexity());
}
@@ -5685,7 +5681,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
private void addManagedProfile(
ComponentName admin, int adminUid, ComponentName copyFromAdmin) throws Exception {
final int userId = UserHandle.getUserId(adminUid);
- getServices().addUser(userId, UserInfo.FLAG_MANAGED_PROFILE, UserHandle.USER_SYSTEM);
+ getServices().addUser(userId, 0, UserManager.USER_TYPE_PROFILE_MANAGED,
+ UserHandle.USER_SYSTEM);
mContext.callerPermissions.addAll(OWNER_SETUP_PERMISSIONS);
setUpPackageManagerForFakeAdmin(admin, adminUid, copyFromAdmin);
dpm.setActiveAdmin(admin, false, userId);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index 6a0d9265f594..7a2350eb4402 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -185,8 +185,8 @@ public class MockSystemServices {
// Add the system user with a fake profile group already set up (this can happen in the real
// world if a managed profile is added and then removed).
- systemUserDataDir =
- addUser(UserHandle.USER_SYSTEM, UserInfo.FLAG_PRIMARY, UserHandle.USER_SYSTEM);
+ systemUserDataDir = addUser(UserHandle.USER_SYSTEM, UserInfo.FLAG_PRIMARY,
+ UserManager.USER_TYPE_FULL_SYSTEM, UserHandle.USER_SYSTEM);
// System user is always running.
setUserRunning(UserHandle.USER_SYSTEM, true);
@@ -208,26 +208,21 @@ public class MockSystemServices {
mBroadcastReceivers.removeIf(r -> r.receiver == receiver);
}
- public File addUser(int userId, int flags) {
- return addUser(userId, flags, UserInfo.NO_PROFILE_GROUP_ID);
+ public File addUser(int userId, int flags, String type) {
+ return addUser(userId, flags, type, UserInfo.NO_PROFILE_GROUP_ID);
}
- public File addUser(int userId, int flags, int profileGroupId) {
+ public File addUser(int userId, int flags, String type, int profileGroupId) {
// Set up (default) UserInfo for CALLER_USER_HANDLE.
final UserInfo uh = new UserInfo(userId, "user" + userId, flags);
+
+ uh.userType = type;
uh.profileGroupId = profileGroupId;
when(userManager.getUserInfo(eq(userId))).thenReturn(uh);
-
mUserInfos.add(uh);
when(userManager.getUsers()).thenReturn(mUserInfos);
when(userManager.getUsers(anyBoolean())).thenReturn(mUserInfos);
when(userManager.isUserRunning(eq(new UserHandle(userId)))).thenReturn(true);
- when(userManager.getUserInfo(anyInt())).thenAnswer(
- invocation -> {
- final int userId1 = (int) invocation.getArguments()[0];
- return getUserInfo(userId1);
- }
- );
when(userManager.getProfileParent(anyInt())).thenAnswer(
invocation -> {
final int userId1 = (int) invocation.getArguments()[0];
@@ -308,7 +303,7 @@ public class MockSystemServices {
*/
public void addUsers(int... userIds) {
for (final int userId : userIds) {
- addUser(userId, 0);
+ addUser(userId, 0, "");
}
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java
deleted file mode 100644
index d1c2fd0fa9dd..000000000000
--- a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2018 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.locksettings;
-
-import static com.android.server.testutils.TestUtils.assertExpectException;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.os.RemoteException;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.internal.widget.LockscreenCredential;
-import com.android.internal.widget.VerifyCredentialResponse;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-
-import java.util.ArrayList;
-
-/**
- * Run the synthetic password tests with caching enabled.
- *
- * By default, those tests run without caching. Untrusted credential reset depends on caching so
- * this class included those tests.
- */
-@SmallTest
-@Presubmit
-@RunWith(AndroidJUnit4.class)
-public class CachedSyntheticPasswordTests extends SyntheticPasswordTests {
-
- @Before
- public void enableSpCache() throws Exception {
- enableSpCaching(true);
- }
-
- private void enableSpCaching(boolean enable) {
- when(mDevicePolicyManagerInternal
- .canUserHaveUntrustedCredentialReset(anyInt())).thenReturn(enable);
- }
-
- @Test
- public void testSyntheticPasswordClearCredentialUntrusted() throws RemoteException {
- final LockscreenCredential password = newPassword("password");
- final LockscreenCredential newPassword = newPassword("newpassword");
-
- initializeCredentialUnderSP(password, PRIMARY_USER_ID);
- long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
- // clear password
- mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID, true);
- assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
-
- // set a new password
- mService.setLockCredential(newPassword, nonePassword(), PRIMARY_USER_ID,
- false);
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- newPassword, 0, PRIMARY_USER_ID)
- .getResponseCode());
- assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
- }
-
- @Test
- public void testSyntheticPasswordChangeCredentialUntrusted() throws RemoteException {
- final LockscreenCredential password = newPassword("password");
- final LockscreenCredential newPassword = newPassword("newpassword");
-
- initializeCredentialUnderSP(password, PRIMARY_USER_ID);
- long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
- // Untrusted change password
- mService.setLockCredential(newPassword, nonePassword(), PRIMARY_USER_ID,
- true);
- assertNotEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
- assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
-
- // Verify the password
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- newPassword, 0, PRIMARY_USER_ID).getResponseCode());
- }
-
- @Test
- public void testUntrustedCredentialChangeMaintainsAuthSecret() throws RemoteException {
- final LockscreenCredential password = newPassword("password");
- final LockscreenCredential newPassword = newPassword("newpassword");
-
- initializeCredentialUnderSP(password, PRIMARY_USER_ID);
- // Untrusted change password
- mService.setLockCredential(newPassword, nonePassword(), PRIMARY_USER_ID,
- true);
-
- // Verify the password
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- newPassword, 0, PRIMARY_USER_ID)
- .getResponseCode());
-
- // Ensure the same secret was passed each time
- ArgumentCaptor<ArrayList<Byte>> secret = ArgumentCaptor.forClass(ArrayList.class);
- verify(mAuthSecretService, atLeastOnce()).primaryUserCredential(secret.capture());
- assertEquals(1, secret.getAllValues().stream().distinct().count());
- }
-
- @Test
- public void testUntrustedCredentialChangeBlockedIfSpNotCached() throws RemoteException {
- final LockscreenCredential password = newPassword("password");
- final LockscreenCredential newPassword = newPassword("newpassword");
-
- // Disable caching for this test
- enableSpCaching(false);
-
- initializeCredentialUnderSP(password, PRIMARY_USER_ID);
- flushHandlerTasks();
-
- long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
- // Untrusted change password
- assertExpectException(
- IllegalStateException.class,
- /* messageRegex= */ "Untrusted credential reset not possible without cached SP",
- () -> mService.setLockCredential(newPassword, nonePassword(),
- PRIMARY_USER_ID, true));
- assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
-
- // Verify the new password doesn't work but the old one still does
- assertEquals(VerifyCredentialResponse.RESPONSE_ERROR, mService.verifyCredential(
- newPassword, 0, PRIMARY_USER_ID)
- .getResponseCode());
- assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
- password, 0, PRIMARY_USER_ID)
- .getResponseCode());
- }
-
-}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
index 8c8edfad231f..abfda7725b7d 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTests.java
@@ -93,7 +93,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("password"), sid);
assertFalse(mService.setLockCredential(newPassword("newpwd"), newPassword("badpwd"),
- PRIMARY_USER_ID, false));
+ PRIMARY_USER_ID));
assertVerifyCredentials(PRIMARY_USER_ID, newPassword("password"), sid);
}
@@ -101,7 +101,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
public void testClearPasswordPrimaryUser() throws RemoteException {
initializeStorageWithCredential(PRIMARY_USER_ID, newPassword("password"), 1234);
assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"),
- PRIMARY_USER_ID, false));
+ PRIMARY_USER_ID));
assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(PRIMARY_USER_ID));
assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
}
@@ -111,7 +111,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
final LockscreenCredential firstUnifiedPassword = newPassword("pwd-1");
final LockscreenCredential secondUnifiedPassword = newPassword("pwd-2");
assertTrue(mService.setLockCredential(firstUnifiedPassword,
- nonePassword(), PRIMARY_USER_ID, false));
+ nonePassword(), PRIMARY_USER_ID));
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
@@ -146,15 +146,14 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
mStorageManager.setIgnoreBadUnlock(true);
// Change primary password and verify that profile SID remains
assertTrue(mService.setLockCredential(
- secondUnifiedPassword, firstUnifiedPassword, PRIMARY_USER_ID, false));
+ secondUnifiedPassword, firstUnifiedPassword, PRIMARY_USER_ID));
mStorageManager.setIgnoreBadUnlock(false);
assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
assertNull(mGateKeeperService.getAuthToken(TURNED_OFF_PROFILE_USER_ID));
// Clear unified challenge
assertTrue(mService.setLockCredential(nonePassword(),
- secondUnifiedPassword, PRIMARY_USER_ID,
- false));
+ secondUnifiedPassword, PRIMARY_USER_ID));
assertEquals(0, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
assertEquals(0, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
assertEquals(0, mGateKeeperService.getSecureUserId(TURNED_OFF_PROFILE_USER_ID));
@@ -166,7 +165,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
final LockscreenCredential profilePassword = newPassword("profile");
assertTrue(mService.setLockCredential(primaryPassword,
nonePassword(),
- PRIMARY_USER_ID, false));
+ PRIMARY_USER_ID));
/* Currently in LockSettingsService.setLockCredential, unlockUser() is called with the new
* credential as part of verifyCredential() before the new credential is committed in
* StorageManager. So we relax the check in our mock StorageManager to allow that.
@@ -174,7 +173,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
mStorageManager.setIgnoreBadUnlock(true);
assertTrue(mService.setLockCredential(profilePassword,
nonePassword(),
- MANAGED_PROFILE_USER_ID, false));
+ MANAGED_PROFILE_USER_ID));
mStorageManager.setIgnoreBadUnlock(false);
final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
@@ -201,7 +200,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
// Change primary credential and make sure we don't affect profile
mStorageManager.setIgnoreBadUnlock(true);
assertTrue(mService.setLockCredential(
- newPassword("pwd"), primaryPassword, PRIMARY_USER_ID, false));
+ newPassword("pwd"), primaryPassword, PRIMARY_USER_ID));
mStorageManager.setIgnoreBadUnlock(false);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
profilePassword, 0, MANAGED_PROFILE_USER_ID)
@@ -214,8 +213,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
newPassword("password"),
nonePassword(),
- PRIMARY_USER_ID,
- false));
+ PRIMARY_USER_ID));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, "password".getBytes(),
@@ -228,8 +226,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
newPattern("12345"),
nonePassword(),
- MANAGED_PROFILE_USER_ID,
- false));
+ MANAGED_PROFILE_USER_ID));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_PATTERN, "12345".getBytes(),
@@ -247,8 +244,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
newPassword("newPassword"),
newPattern("12345"),
- MANAGED_PROFILE_USER_ID,
- false));
+ MANAGED_PROFILE_USER_ID));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, "newPassword".getBytes(),
@@ -263,8 +259,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
newPattern("12345"),
nonePassword(),
- PRIMARY_USER_ID,
- false));
+ PRIMARY_USER_ID));
verify(mRecoverableKeyStoreManager, never())
.lockScreenSecretChanged(
@@ -284,8 +279,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
newCredential,
oldCredential,
- PRIMARY_USER_ID,
- false));
+ PRIMARY_USER_ID));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, newCredential.getCredential(),
@@ -305,8 +299,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
nonePassword(),
newPassword("oldPassword"),
- PRIMARY_USER_ID,
- false));
+ PRIMARY_USER_ID));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_NONE, null, PRIMARY_USER_ID);
@@ -322,7 +315,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
1234);
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
- mService.setLockCredential(nonePassword(), newPattern("123654"), PRIMARY_USER_ID, false);
+ mService.setLockCredential(nonePassword(), newPattern("123654"), PRIMARY_USER_ID);
// Verify fingerprint is removed
verify(mFingerprintManager).remove(any(), eq(PRIMARY_USER_ID), any());
@@ -343,8 +336,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
profilePassword,
nonePassword(),
- MANAGED_PROFILE_USER_ID,
- false));
+ MANAGED_PROFILE_USER_ID));
verify(mRecoverableKeyStoreManager)
.lockScreenSecretChanged(CREDENTIAL_TYPE_PASSWORD, profilePassword.getCredential(),
@@ -390,8 +382,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
assertTrue(mService.setLockCredential(
pattern,
nonePassword(),
- MANAGED_PROFILE_USER_ID,
- false));
+ MANAGED_PROFILE_USER_ID));
reset(mRecoverableKeyStoreManager);
mService.verifyCredential(pattern, 1, MANAGED_PROFILE_USER_ID);
@@ -426,7 +417,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
private void testCreateCredential(int userId, LockscreenCredential credential)
throws RemoteException {
- assertTrue(mService.setLockCredential(credential, nonePassword(), userId, false));
+ assertTrue(mService.setLockCredential(credential, nonePassword(), userId));
assertVerifyCredentials(userId, credential, -1);
}
@@ -435,7 +426,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
mHasSecureLockScreen = false;
try {
- mService.setLockCredential(credential, null, userId, false);
+ mService.setLockCredential(credential, null, userId);
fail("An exception should have been thrown.");
} catch (UnsupportedOperationException e) {
// Success - the exception was expected.
@@ -448,7 +439,7 @@ public class LockSettingsServiceTests extends BaseLockSettingsServiceTests {
LockscreenCredential oldCredential) throws RemoteException {
final long sid = 1234;
initializeStorageWithCredential(userId, oldCredential, sid);
- assertTrue(mService.setLockCredential(newCredential, oldCredential, userId, false));
+ assertTrue(mService.setLockCredential(newCredential, oldCredential, userId));
assertVerifyCredentials(userId, newCredential, sid);
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java
index 27af9e2dfd6f..4b3f7b5d08ef 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockscreenFrpTest.java
@@ -48,7 +48,7 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
@Test
public void testFrpCredential_setPin() {
- mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
assertEquals(CREDENTIAL_TYPE_PIN, mService.getCredentialType(USER_FRP));
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
@@ -57,7 +57,7 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
@Test
public void testFrpCredential_setPattern() {
- mService.setLockCredential(newPattern("4321"), nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPattern("4321"), nonePassword(), PRIMARY_USER_ID);
assertEquals(CREDENTIAL_TYPE_PATTERN, mService.getCredentialType(USER_FRP));
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
@@ -66,7 +66,7 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
@Test
public void testFrpCredential_setPassword() {
- mService.setLockCredential(newPassword("4321"), nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPassword("4321"), nonePassword(), PRIMARY_USER_ID);
assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(USER_FRP));
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
@@ -75,8 +75,8 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
@Test
public void testFrpCredential_changeCredential() {
- mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID, false);
- mService.setLockCredential(newPattern("5678"), newPassword("1234"), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID);
+ mService.setLockCredential(newPattern("5678"), newPassword("1234"), PRIMARY_USER_ID);
assertEquals(CREDENTIAL_TYPE_PATTERN, mService.getCredentialType(USER_FRP));
assertEquals(VerifyCredentialResponse.RESPONSE_OK,
@@ -85,16 +85,16 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
@Test
public void testFrpCredential_removeCredential() {
- mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID);
assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(USER_FRP));
- mService.setLockCredential(nonePassword(), newPassword("1234"), PRIMARY_USER_ID, false);
+ mService.setLockCredential(nonePassword(), newPassword("1234"), PRIMARY_USER_ID);
assertEquals(CREDENTIAL_TYPE_NONE, mService.getCredentialType(USER_FRP));
}
@Test
public void testFrpCredential_cannotVerifyAfterProvsioning() {
- mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
mSettings.setDeviceProvisioned(true);
assertEquals(VerifyCredentialResponse.RESPONSE_ERROR,
@@ -103,7 +103,7 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
@Test
public void testFrpCredential_legacyPinTypePersistentData() {
- mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPin("1234"), nonePassword(), PRIMARY_USER_ID);
PersistentData data = mStorage.readPersistentDataBlock();
// Tweak the existing persistent data to make it look like one with legacy credential type
assertEquals(CREDENTIAL_TYPE_PIN, data.payload[3]);
@@ -119,7 +119,7 @@ public class LockscreenFrpTest extends BaseLockSettingsServiceTests {
@Test
public void testFrpCredential_legacyPasswordTypePersistentData() {
- mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPassword("1234"), nonePassword(), PRIMARY_USER_ID);
PersistentData data = mStorage.readPersistentDataBlock();
// Tweak the existing persistent data to make it look like one with legacy credential type
assertEquals(CREDENTIAL_TYPE_PASSWORD, data.payload[3]);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index 49858482fdf6..d6ef2d459769 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -106,7 +106,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
final LockscreenCredential password = newPassword("testPasswordMigration-password");
disableSyntheticPassword();
- assertTrue(mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID, false));
+ assertTrue(mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID));
long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
enableSyntheticPassword();
@@ -128,7 +128,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
protected void initializeCredentialUnderSP(LockscreenCredential password, int userId)
throws RemoteException {
enableSyntheticPassword();
- mService.setLockCredential(password, nonePassword(), userId, false);
+ mService.setLockCredential(password, nonePassword(), userId);
assertEquals(CREDENTIAL_TYPE_PASSWORD, mService.getCredentialType(userId));
assertTrue(mService.isSyntheticPasswordBasedCredential(userId));
}
@@ -140,7 +140,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
- mService.setLockCredential(newPassword, password, PRIMARY_USER_ID, false);
+ mService.setLockCredential(newPassword, password, PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
newPassword, 0, PRIMARY_USER_ID)
.getResponseCode());
@@ -170,12 +170,11 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
// clear password
- mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID, false);
+ mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID);
assertEquals(0 ,mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
// set a new password
- mService.setLockCredential(badPassword, nonePassword(),
- PRIMARY_USER_ID, false);
+ mService.setLockCredential(badPassword, nonePassword(), PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
badPassword, 0, PRIMARY_USER_ID)
.getResponseCode());
@@ -188,7 +187,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
LockscreenCredential badPassword = newPassword("new");
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
- mService.setLockCredential(badPassword, password, PRIMARY_USER_ID, false);
+ mService.setLockCredential(badPassword, password, PRIMARY_USER_ID);
assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
badPassword, 0, PRIMARY_USER_ID)
.getResponseCode());
@@ -245,7 +244,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
public void testSyntheticPasswordButNoCredentialPassesAuthSecret() throws RemoteException {
LockscreenCredential password = newPassword("getASyntheticPassword");
initializeCredentialUnderSP(password, PRIMARY_USER_ID);
- mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID, false);
+ mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID);
reset(mAuthSecretService);
mService.onUnlockUser(PRIMARY_USER_ID);
@@ -257,7 +256,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
public void testManagedProfileUnifiedChallengeMigration() throws RemoteException {
LockscreenCredential UnifiedPassword = newPassword("unified-pwd");
disableSyntheticPassword();
- mService.setLockCredential(UnifiedPassword, nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(UnifiedPassword, nonePassword(), PRIMARY_USER_ID);
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
@@ -292,9 +291,8 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
LockscreenCredential primaryPassword = newPassword("primary");
LockscreenCredential profilePassword = newPassword("profile");
disableSyntheticPassword();
- mService.setLockCredential(primaryPassword, nonePassword(), PRIMARY_USER_ID, false);
- mService.setLockCredential(profilePassword, nonePassword(),
- MANAGED_PROFILE_USER_ID, false);
+ mService.setLockCredential(primaryPassword, nonePassword(), PRIMARY_USER_ID);
+ mService.setLockCredential(profilePassword, nonePassword(), MANAGED_PROFILE_USER_ID);
final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
@@ -404,7 +402,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
mService.verifyCredential(password, 0, PRIMARY_USER_ID).getResponseCode();
assertTrue(mLocalService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
- mService.setLockCredential(pattern, password, PRIMARY_USER_ID, false);
+ mService.setLockCredential(pattern, password, PRIMARY_USER_ID);
mLocalService.setLockCredentialWithToken(newPassword, handle, token, PRIMARY_USER_ID);
@@ -433,7 +431,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
// initialized but the user currently has no password
initializeCredentialUnderSP(newPassword("password"), PRIMARY_USER_ID);
assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"),
- PRIMARY_USER_ID, false));
+ PRIMARY_USER_ID));
assertTrue(mService.isSyntheticPasswordBasedCredential(PRIMARY_USER_ID));
long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
@@ -449,7 +447,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
LockscreenCredential password = newPassword("password");
// Set up pre-SP user password
disableSyntheticPassword();
- mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID);
enableSyntheticPassword();
long handle = mLocalService.addEscrowToken(token, PRIMARY_USER_ID, null);
@@ -507,11 +505,11 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
@Test
public void testGetHashFactorPrimaryUser() throws RemoteException {
LockscreenCredential password = newPassword("password");
- mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(password, nonePassword(), PRIMARY_USER_ID);
byte[] hashFactor = mService.getHashFactor(password, PRIMARY_USER_ID);
assertNotNull(hashFactor);
- mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID, false);
+ mService.setLockCredential(nonePassword(), password, PRIMARY_USER_ID);
byte[] newHashFactor = mService.getHashFactor(nonePassword(), PRIMARY_USER_ID);
assertNotNull(newHashFactor);
// Hash factor should never change after password change/removal
@@ -521,7 +519,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
@Test
public void testGetHashFactorManagedProfileUnifiedChallenge() throws RemoteException {
LockscreenCredential pattern = newPattern("1236");
- mService.setLockCredential(pattern, nonePassword(), PRIMARY_USER_ID, false);
+ mService.setLockCredential(pattern, nonePassword(), PRIMARY_USER_ID);
mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
assertNotNull(mService.getHashFactor(null, MANAGED_PROFILE_USER_ID));
}
@@ -530,9 +528,8 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
public void testGetHashFactorManagedProfileSeparateChallenge() throws RemoteException {
LockscreenCredential primaryPassword = newPassword("primary");
LockscreenCredential profilePassword = newPassword("profile");
- mService.setLockCredential(primaryPassword, nonePassword(), PRIMARY_USER_ID, false);
- mService.setLockCredential(profilePassword, nonePassword(),
- MANAGED_PROFILE_USER_ID, false);
+ mService.setLockCredential(primaryPassword, nonePassword(), PRIMARY_USER_ID);
+ mService.setLockCredential(profilePassword, nonePassword(), MANAGED_PROFILE_USER_ID);
assertNotNull(
mService.getHashFactor(profilePassword, MANAGED_PROFILE_USER_ID));
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
index 178f38aac0b7..fb9c68a5b70d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -68,7 +68,7 @@ public class ApexManagerTest {
@Before
public void setUp() throws RemoteException {
mContext = InstrumentationRegistry.getInstrumentation().getContext();
- mApexManager = new ApexManager.ApexManagerImpl(mContext, mApexService);
+ mApexManager = new ApexManager.ApexManagerImpl(mApexService);
}
@Test
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 92198fa8cb0c..f608babd062c 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -20,6 +20,7 @@ android_test {
"androidx.test.rules", "hamcrest-library",
"mockito-target-inline-minus-junit4",
"platform-test-annotations",
+ "platformprotosnano",
"hamcrest-library",
"testables",
"truth-prebuilt",
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PulledStatsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PulledStatsTest.java
new file mode 100644
index 000000000000..f685c68f4160
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PulledStatsTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.server.notification;
+
+import static com.android.server.notification.NotificationManagerService.REPORT_REMOTE_VIEWS;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotSame;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.service.notification.nano.NotificationRemoteViewsProto;
+import android.test.MoreAsserts;
+import android.util.proto.ProtoOutputStream;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.UiServiceTestCase;
+
+import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
+
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+@SmallTest
+public class PulledStatsTest extends UiServiceTestCase {
+
+ @Test
+ public void testPulledStats_Empty() {
+ PulledStats stats = new PulledStats(0L);
+ assertEquals(0L, stats.endTimeMs());
+ }
+
+ @Test
+ public void testPulledStats_UnknownReport() {
+ PulledStats stats = new PulledStats(0L);
+ stats.addUndecoratedPackage("foo", 456);
+ stats.addUndecoratedPackage("bar", 123);
+
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ final ProtoOutputStream proto = new ProtoOutputStream(bytes);
+ stats.writeToProto(1023123, proto); // a very large number
+ proto.flush();
+
+ // expect empty output in response to an unrecognized request
+ assertEquals(0L, bytes.size());
+ }
+
+ @Test
+ public void testPulledStats_RemoteViewReportPackages() {
+ List<String> expectedPkgs = new ArrayList<>(2);
+ expectedPkgs.add("foo");
+ expectedPkgs.add("bar");
+
+ PulledStats stats = new PulledStats(0L);
+ for(String pkg: expectedPkgs) {
+ stats.addUndecoratedPackage(pkg, 111);
+ }
+
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ final ProtoOutputStream protoStream = new ProtoOutputStream(bytes);
+ stats.writeToProto(REPORT_REMOTE_VIEWS, protoStream);
+ protoStream.flush();
+
+ try {
+ NotificationRemoteViewsProto proto =
+ NotificationRemoteViewsProto.parseFrom(bytes.toByteArray());
+ List<String> actualPkgs = new ArrayList<>(2);
+ for(int i = 0 ; i < proto.packageRemoteViewInfo.length; i++) {
+ actualPkgs.add(proto.packageRemoteViewInfo[i].packageName);
+ }
+ assertEquals(2, actualPkgs.size());
+ assertTrue("missing packages", actualPkgs.containsAll(expectedPkgs));
+ assertTrue("unexpected packages", expectedPkgs.containsAll(actualPkgs));
+ } catch (InvalidProtocolBufferNanoException e) {
+ e.printStackTrace();
+ fail("writeToProto generated unparsable output");
+ }
+
+ }
+ @Test
+ public void testPulledStats_RemoteViewReportEndTime() {
+ List<String> expectedPkgs = new ArrayList<>(2);
+ expectedPkgs.add("foo");
+ expectedPkgs.add("bar");
+
+ PulledStats stats = new PulledStats(0L);
+ long t = 111;
+ for(String pkg: expectedPkgs) {
+ t += 1000;
+ stats.addUndecoratedPackage(pkg, t);
+ }
+ assertEquals(t, stats.endTimeMs());
+ }
+
+}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index e34824c57fb2..1996dd4f6545 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -236,7 +236,7 @@ public class UsageStatsDatabase {
return false;
}
}
- } catch (IOException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Failed to check-in", e);
return false;
}
@@ -744,7 +744,7 @@ public class UsageStatsDatabase {
IntervalStats stats = new IntervalStats();
readLocked(f, stats);
return stats;
- } catch (IOException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Failed to read usage stats file", e);
}
}
@@ -862,7 +862,7 @@ public class UsageStatsDatabase {
if (beginTime < stats.endTime) {
combiner.combine(stats, false, results);
}
- } catch (IOException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Failed to read usage stats file", e);
// We continue so that we return results that are not
// corrupt.
@@ -1009,7 +1009,8 @@ public class UsageStatsDatabase {
}
}
- private void writeLocked(AtomicFile file, IntervalStats stats) throws IOException {
+ private void writeLocked(AtomicFile file, IntervalStats stats)
+ throws IOException, RuntimeException {
if (mCurrentVersion <= 3) {
Slog.wtf(TAG, "Attempting to write UsageStats as XML with version " + mCurrentVersion);
return;
@@ -1018,7 +1019,7 @@ public class UsageStatsDatabase {
}
private static void writeLocked(AtomicFile file, IntervalStats stats, int version,
- PackagesTokenData packagesTokenData) throws IOException {
+ PackagesTokenData packagesTokenData) throws IOException, RuntimeException {
FileOutputStream fos = file.startWrite();
try {
writeLocked(fos, stats, version, packagesTokenData);
@@ -1031,7 +1032,7 @@ public class UsageStatsDatabase {
}
private static void writeLocked(OutputStream out, IntervalStats stats, int version,
- PackagesTokenData packagesTokenData) throws IOException {
+ PackagesTokenData packagesTokenData) throws RuntimeException {
switch (version) {
case 1:
case 2:
@@ -1041,7 +1042,7 @@ public class UsageStatsDatabase {
case 4:
try {
UsageStatsProto.write(out, stats);
- } catch (IOException | IllegalArgumentException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Unable to write interval stats to proto.", e);
}
break;
@@ -1049,7 +1050,7 @@ public class UsageStatsDatabase {
stats.obfuscateData(packagesTokenData);
try {
UsageStatsProtoV2.write(out, stats);
- } catch (IOException | IllegalArgumentException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Unable to write interval stats to proto.", e);
}
break;
@@ -1060,7 +1061,8 @@ public class UsageStatsDatabase {
}
}
- private void readLocked(AtomicFile file, IntervalStats statsOut) throws IOException {
+ private void readLocked(AtomicFile file, IntervalStats statsOut)
+ throws IOException, RuntimeException {
if (mCurrentVersion <= 3) {
Slog.wtf(TAG, "Reading UsageStats as XML; current database version: "
+ mCurrentVersion);
@@ -1072,7 +1074,7 @@ public class UsageStatsDatabase {
* Returns {@code true} if any stats were omitted while reading, {@code false} otherwise.
*/
private static boolean readLocked(AtomicFile file, IntervalStats statsOut, int version,
- PackagesTokenData packagesTokenData) throws IOException {
+ PackagesTokenData packagesTokenData) throws IOException, RuntimeException {
boolean dataOmitted = false;
try {
FileInputStream in = file.openRead();
@@ -1098,7 +1100,7 @@ public class UsageStatsDatabase {
* Returns {@code true} if any stats were omitted while reading, {@code false} otherwise.
*/
private static boolean readLocked(InputStream in, IntervalStats statsOut, int version,
- PackagesTokenData packagesTokenData) throws IOException {
+ PackagesTokenData packagesTokenData) throws RuntimeException {
boolean dataOmitted = false;
switch (version) {
case 1:
@@ -1114,14 +1116,14 @@ public class UsageStatsDatabase {
case 4:
try {
UsageStatsProto.read(in, statsOut);
- } catch (IOException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Unable to read interval stats from proto.", e);
}
break;
case 5:
try {
UsageStatsProtoV2.read(in, statsOut);
- } catch (IOException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Unable to read interval stats from proto.", e);
}
dataOmitted = statsOut.deobfuscateData(packagesTokenData);
@@ -1145,7 +1147,7 @@ public class UsageStatsDatabase {
try (FileInputStream in = new AtomicFile(mPackageMappingsFile).openRead()) {
UsageStatsProtoV2.readObfuscatedData(in, mPackagesTokenData);
- } catch (IOException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Failed to read the obfuscated packages mapping file.", e);
return;
}
@@ -1174,7 +1176,7 @@ public class UsageStatsDatabase {
UsageStatsProtoV2.writeObfuscatedData(fos, mPackagesTokenData);
file.finishWrite(fos);
fos = null;
- } catch (IOException | IllegalArgumentException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Unable to write obfuscated data to proto.", e);
} finally {
file.failWrite(fos);
@@ -1414,8 +1416,8 @@ public class UsageStatsDatabase {
try {
stats.beginTime = in.readLong();
readLocked(in, stats, version, mPackagesTokenData);
- } catch (IOException ioe) {
- Slog.d(TAG, "DeSerializing IntervalStats Failed", ioe);
+ } catch (Exception e) {
+ Slog.d(TAG, "DeSerializing IntervalStats Failed", e);
stats = null;
}
return stats;
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 064922386773..c900f386b438 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -653,18 +653,20 @@ public class UsageStatsService extends SystemService implements
}
Arrays.sort(pendingEventsFiles);
- for (int i = 0; i < pendingEventsFiles.length; i++) {
+ final int numFiles = pendingEventsFiles.length;
+ for (int i = 0; i < numFiles; i++) {
final AtomicFile af = new AtomicFile(pendingEventsFiles[i]);
+ final LinkedList<Event> tmpEvents = new LinkedList<>();
try {
try (FileInputStream in = af.openRead()) {
- UsageStatsProtoV2.readPendingEvents(in, pendingEvents);
+ UsageStatsProtoV2.readPendingEvents(in, tmpEvents);
}
- } catch (IOException e) {
- // Even if one file read fails, exit here to keep all events in order on disk -
- // they will be read and processed the next time user is unlocked.
+ // only add to the pending events if the read was successful
+ pendingEvents.addAll(tmpEvents);
+ } catch (Exception e) {
+ // Most likely trying to read a corrupted file - log the failure and continue
+ // reading the other pending event files.
Slog.e(TAG, "Could not read " + pendingEventsFiles[i] + " for user " + userId);
- pendingEvents.clear();
- return;
}
}
}
@@ -691,7 +693,7 @@ public class UsageStatsService extends SystemService implements
af.finishWrite(fos);
fos = null;
pendingEvents.clear();
- } catch (IOException | IllegalArgumentException e) {
+ } catch (Exception e) {
Slog.e(TAG, "Failed to write " + pendingEventsFile.getAbsolutePath()
+ " for user " + userId);
} finally {
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index ace2131835c0..cf705f466e48 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -54,6 +54,7 @@ import android.os.ParcelUuid;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.provider.Telephony.SimInfo;
import android.telephony.euicc.EuiccManager;
import android.telephony.ims.ImsMmTelManager;
import android.util.DisplayMetrics;
@@ -129,7 +130,7 @@ public class SubscriptionManager {
/** @hide */
@UnsupportedAppUsage
- public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
+ public static final Uri CONTENT_URI = SimInfo.CONTENT_URI;
/**
* Generates a content {@link Uri} used to receive updates on simInfo change
diff --git a/tests/FlickerTests/AndroidTest.xml b/tests/FlickerTests/AndroidTest.xml
index d433df56bc00..d1da47f0f9d8 100644
--- a/tests/FlickerTests/AndroidTest.xml
+++ b/tests/FlickerTests/AndroidTest.xml
@@ -25,6 +25,6 @@
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
<option name="directory-keys" value="/sdcard/flicker" />
<option name="collect-on-run-ended-only" value="true" />
- <option name="clean-up" value="false" />
+ <option name="clean-up" value="true" />
</metrics_collector>
</configuration>
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index e30878157a26..ef8facec9752 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -118,7 +118,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// The failed packages should be the same as the registered ones to ensure registration is
// done successfully
@@ -135,7 +136,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer2, Arrays.asList(APP_A, APP_B), SHORT_DURATION);
raiseFatalFailureAndDispatch(watchdog,
Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
- new VersionedPackage(APP_B, VERSION_CODE)));
+ new VersionedPackage(APP_B, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// The failed packages should be the same as the registered ones to ensure registration is
// done successfully
@@ -151,7 +153,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
watchdog.unregisterHealthObserver(observer);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should have no failed packages to ensure unregistration is done successfully
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
@@ -167,7 +170,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION);
watchdog.unregisterHealthObserver(observer2);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// observer1 should receive failed packages as intended.
assertThat(observer1.mHealthCheckFailedPackages).containsExactly(APP_A);
@@ -183,7 +187,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
moveTimeForwardAndDispatch(SHORT_DURATION);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should have no failed packages for the fatal failure is raised after expiration
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
@@ -199,7 +204,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), LONG_DURATION);
moveTimeForwardAndDispatch(SHORT_DURATION);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should have no failed packages for the fatal failure is raised after expiration
assertThat(observer1.mHealthCheckFailedPackages).isEmpty();
@@ -226,7 +232,8 @@ public class PackageWatchdogTest {
moveTimeForwardAndDispatch((SHORT_DURATION / 2) + 1);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify that we receive failed packages as expected for APP_A not expired
assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A);
@@ -252,7 +259,8 @@ public class PackageWatchdogTest {
watchdog2.registerHealthObserver(observer2);
raiseFatalFailureAndDispatch(watchdog2,
Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
- new VersionedPackage(APP_B, VERSION_CODE)));
+ new VersionedPackage(APP_B, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should receive failed packages as expected to ensure observers are persisted and
// resumed correctly
@@ -274,7 +282,8 @@ public class PackageWatchdogTest {
// Then fail APP_A below the threshold
for (int i = 0; i < watchdog.getTriggerFailureCount() - 1; i++) {
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
}
// Run handler so package failures are dispatched to observers
@@ -301,7 +310,8 @@ public class PackageWatchdogTest {
// Then fail APP_C (not observed) above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_C, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_C, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify that observers are not notified
assertThat(observer1.mHealthCheckFailedPackages).isEmpty();
@@ -331,7 +341,8 @@ public class PackageWatchdogTest {
// Then fail APP_A (different version) above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, differentVersionCode)));
+ Arrays.asList(new VersionedPackage(APP_A, differentVersionCode)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify that observers are not notified
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
@@ -368,7 +379,8 @@ public class PackageWatchdogTest {
Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
new VersionedPackage(APP_B, VERSION_CODE),
new VersionedPackage(APP_C, VERSION_CODE),
- new VersionedPackage(APP_D, VERSION_CODE)));
+ new VersionedPackage(APP_D, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify least impact observers are notifed of package failures
List<String> observerNonePackages = observerNone.mMitigatedPackages;
@@ -411,7 +423,8 @@ public class PackageWatchdogTest {
// Then fail APP_A above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify only observerFirst is notifed
assertThat(observerFirst.mMitigatedPackages).containsExactly(APP_A);
@@ -424,7 +437,8 @@ public class PackageWatchdogTest {
// Then fail APP_A again above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify only observerSecond is notifed cos it has least impact
assertThat(observerSecond.mMitigatedPackages).containsExactly(APP_A);
@@ -437,7 +451,8 @@ public class PackageWatchdogTest {
// Then fail APP_A again above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify only observerFirst is notifed cos it has the only action
assertThat(observerFirst.mMitigatedPackages).containsExactly(APP_A);
@@ -450,7 +465,8 @@ public class PackageWatchdogTest {
// Then fail APP_A again above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify no observer is notified cos no actions left
assertThat(observerFirst.mMitigatedPackages).isEmpty();
@@ -474,7 +490,8 @@ public class PackageWatchdogTest {
// Then fail APP_A above the threshold
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// Verify only one observer is notifed
assertThat(observer1.mMitigatedPackages).containsExactly(APP_A);
@@ -746,13 +763,15 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
// Fail APP_A below the threshold which should not trigger package failures
for (int i = 0; i < PackageWatchdog.DEFAULT_TRIGGER_FAILURE_COUNT - 1; i++) {
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
}
mTestLooper.dispatchAll();
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
// One more to trigger the package failure
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A);
}
@@ -773,20 +792,24 @@ public class PackageWatchdogTest {
TestObserver observer = new TestObserver(OBSERVER_NAME_1);
watchdog.startObservingHealth(observer, Arrays.asList(APP_A, APP_B), Long.MAX_VALUE);
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS + 1);
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
// We shouldn't receive APP_A since the interval of 2 failures is greater than
// DEFAULT_TRIGGER_FAILURE_DURATION_MS.
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_TRIGGER_FAILURE_DURATION_MS - 1);
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_B, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
// We should receive APP_B since the interval of 2 failures is less than
@@ -809,7 +832,8 @@ public class PackageWatchdogTest {
// small timeouts.
moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_OBSERVING_DURATION_MS - 100);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should receive APP_A since the observer hasn't expired
assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A);
@@ -827,7 +851,8 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), -1);
moveTimeForwardAndDispatch(PackageWatchdog.DEFAULT_OBSERVING_DURATION_MS + 1);
raiseFatalFailureAndDispatch(watchdog,
- Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
// We should receive nothing since the observer has expired
assertThat(observer.mHealthCheckFailedPackages).isEmpty();
@@ -850,22 +875,59 @@ public class PackageWatchdogTest {
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), Long.MAX_VALUE);
// Raise 2 failures at t=0 and t=900 respectively
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
moveTimeForwardAndDispatch(900);
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
// Raise 2 failures at t=1100
moveTimeForwardAndDispatch(200);
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
- watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
+ watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)),
+ PackageWatchdog.FAILURE_REASON_UNKNOWN);
mTestLooper.dispatchAll();
// We should receive APP_A since there are 3 failures within 1000ms window
assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A);
}
+ /** Test that observers execute correctly for different failure reasons */
+ @Test
+ public void testFailureReasons() {
+ PackageWatchdog watchdog = createWatchdog();
+ TestObserver observer1 = new TestObserver(OBSERVER_NAME_1);
+ TestObserver observer2 = new TestObserver(OBSERVER_NAME_2);
+ TestObserver observer3 = new TestObserver(OBSERVER_NAME_3);
+ TestObserver observer4 = new TestObserver(OBSERVER_NAME_4);
+
+ watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION);
+ watchdog.startObservingHealth(observer2, Arrays.asList(APP_B), SHORT_DURATION);
+ watchdog.startObservingHealth(observer3, Arrays.asList(APP_C), SHORT_DURATION);
+ watchdog.startObservingHealth(observer4, Arrays.asList(APP_D), SHORT_DURATION);
+
+ raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_A,
+ VERSION_CODE)), PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
+ raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_B,
+ VERSION_CODE)), PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
+ raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_C,
+ VERSION_CODE)), PackageWatchdog.FAILURE_REASON_APP_CRASH);
+ raiseFatalFailureAndDispatch(watchdog, Arrays.asList(new VersionedPackage(APP_D,
+ VERSION_CODE)), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING);
+
+ assertThat(observer1.getLastFailureReason()).isEqualTo(
+ PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
+ assertThat(observer2.getLastFailureReason()).isEqualTo(
+ PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK);
+ assertThat(observer3.getLastFailureReason()).isEqualTo(
+ PackageWatchdog.FAILURE_REASON_APP_CRASH);
+ assertThat(observer4.getLastFailureReason()).isEqualTo(
+ PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING);
+ }
+
private void adoptShellPermissions(String... permissions) {
InstrumentationRegistry
.getInstrumentation()
@@ -900,9 +962,9 @@ public class PackageWatchdogTest {
/** Trigger package failures above the threshold. */
private void raiseFatalFailureAndDispatch(PackageWatchdog watchdog,
- List<VersionedPackage> packages) {
+ List<VersionedPackage> packages, int failureReason) {
for (int i = 0; i < watchdog.getTriggerFailureCount(); i++) {
- watchdog.onPackageFailure(packages);
+ watchdog.onPackageFailure(packages, failureReason);
}
mTestLooper.dispatchAll();
}
@@ -936,6 +998,7 @@ public class PackageWatchdogTest {
private static class TestObserver implements PackageHealthObserver {
private final String mName;
private int mImpact;
+ private int mLastFailureReason;
final List<String> mHealthCheckFailedPackages = new ArrayList<>();
final List<String> mMitigatedPackages = new ArrayList<>();
@@ -954,14 +1017,19 @@ public class PackageWatchdogTest {
return mImpact;
}
- public boolean execute(VersionedPackage versionedPackage) {
+ public boolean execute(VersionedPackage versionedPackage, int failureReason) {
mMitigatedPackages.add(versionedPackage.getPackageName());
+ mLastFailureReason = failureReason;
return true;
}
public String getName() {
return mName;
}
+
+ public int getLastFailureReason() {
+ return mLastFailureReason;
+ }
}
private static class TestController extends ExplicitHealthCheckController {
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 6c3bcf039be1..bb541fe2490b 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -304,9 +304,11 @@ void JavaClassGenerator::ProcessStyleable(const ResourceNameRef& name, const Res
auto documentation_remove_iter = std::remove_if(documentation_attrs.begin(),
documentation_attrs.end(),
[&](StyleableAttr entry) -> bool {
- StringPiece attr_comment_line = entry.symbol.value().attribute->GetComment();
- return SkipSymbol(entry.symbol) || attr_comment_line.contains("@removed")
- || attr_comment_line.contains("@hide");
+ if (SkipSymbol(entry.symbol)) {
+ return true;
+ }
+ const StringPiece attr_comment_line = entry.symbol.value().attribute->GetComment();
+ return attr_comment_line.contains("@removed") || attr_comment_line.contains("@hide");
});
documentation_attrs.erase(documentation_remove_iter, documentation_attrs.end());
diff --git a/tools/stats_log_api_gen/java_writer.cpp b/tools/stats_log_api_gen/java_writer.cpp
index 4899fbd3b669..d45c4e7efb12 100644
--- a/tools/stats_log_api_gen/java_writer.cpp
+++ b/tools/stats_log_api_gen/java_writer.cpp
@@ -83,7 +83,7 @@ static int write_java_methods(
// Print method body.
string indent("");
if (DEFAULT_MODULE_NAME != moduleName) {
- fprintf(out, " if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {\n");
+ fprintf(out, " if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {\n");
indent = " ";
}
@@ -116,16 +116,19 @@ static int write_java_methods(
fprintf(out, "%s builder.writeString(arg%d);\n", indent.c_str(), argIndex);
break;
case JAVA_TYPE_BYTE_ARRAY:
- fprintf(out, "%s builder.writeByteArray(arg%d);\n",
- indent.c_str(), argIndex);
+ fprintf(out, "%s builder.writeByteArray(null == arg%d ? new byte[0] : arg%d);\n",
+ indent.c_str(), argIndex, argIndex);
break;
case JAVA_TYPE_ATTRIBUTION_CHAIN:
{
const char* uidName = attributionDecl.fields.front().name.c_str();
const char* tagName = attributionDecl.fields.back().name.c_str();
- fprintf(out, "%s builder.writeAttributionChain(%s, %s);\n",
- indent.c_str(), uidName, tagName);
+ fprintf(out, "%s builder.writeAttributionChain(\n", indent.c_str());
+ fprintf(out, "%s null == %s ? new int[0] : %s,\n",
+ indent.c_str(), uidName, uidName);
+ fprintf(out, "%s null == %s ? new String[0] : %s);\n",
+ indent.c_str(), tagName, tagName);
break;
}
case JAVA_TYPE_KEY_VALUE_PAIR:
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index fccbcf7c101f..b52880e29e30 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -44,7 +44,6 @@ import android.net.wifi.WifiNetworkSuggestion;
import android.os.Messenger;
import android.os.ResultReceiver;
import android.os.WorkSource;
-import android.os.connectivity.WifiActivityEnergyInfo;
/**
* Interface that allows controlling and querying Wi-Fi connectivity.
@@ -55,8 +54,6 @@ interface IWifiManager
{
long getSupportedFeatures();
- WifiActivityEnergyInfo reportActivityInfo();
-
oneway void getWifiActivityEnergyInfoAsync(in IOnWifiActivityEnergyInfoListener listener);
ParceledListSlice getConfiguredNetworks(String packageName, String featureId);
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 0108d5aa936c..86c398b770b7 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -2379,25 +2379,6 @@ public class WifiManager {
}
/**
- * Return the record of {@link WifiActivityEnergyInfo} object that
- * has the activity and energy info. This can be used to ascertain what
- * the controller has been up to, since the last sample.
- *
- * @return a record with {@link WifiActivityEnergyInfo} or null if
- * report is unavailable or unsupported
- * @hide
- */
- public WifiActivityEnergyInfo getControllerActivityEnergyInfo() {
- try {
- synchronized(this) {
- return mService.reportActivityInfo();
- }
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Interface for Wi-Fi activity energy info listener. Should be implemented by applications and
* set when calling {@link WifiManager#getWifiActivityEnergyInfoAsync}.
*
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index e78104d3da38..9fd29ae8d14a 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -23,12 +23,10 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.app.ActivityThread;
import android.net.MacAddress;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.Process;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -46,7 +44,6 @@ import java.util.Objects;
* {@link WifiManager#addNetworkSuggestions(List)}.
*/
public final class WifiNetworkSuggestion implements Parcelable {
-
/**
* Builder used to create {@link WifiNetworkSuggestion} objects.
*/
@@ -563,9 +560,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
mPasspointConfiguration,
mIsAppInteractionRequired,
mIsUserInteractionRequired,
- mIsUserAllowed,
- Process.myUid(),
- ActivityThread.currentApplication().getApplicationContext().getOpPackageName());
+ mIsUserAllowed);
}
}
@@ -592,19 +587,6 @@ public final class WifiNetworkSuggestion implements Parcelable {
* @hide
*/
public final boolean isUserInteractionRequired;
-
- /**
- * The UID of the process initializing this network suggestion.
- * @hide
- */
- public final int suggestorUid;
-
- /**
- * The package name of the process initializing this network suggestion.
- * @hide
- */
- public final String suggestorPackageName;
-
/**
* Whether app share credential with the user, allow user use provided credential to
* connect network manually.
@@ -619,8 +601,6 @@ public final class WifiNetworkSuggestion implements Parcelable {
this.isAppInteractionRequired = false;
this.isUserInteractionRequired = false;
this.isUserAllowedToManuallyConnect = true;
- this.suggestorUid = -1;
- this.suggestorPackageName = null;
}
/** @hide */
@@ -628,18 +608,14 @@ public final class WifiNetworkSuggestion implements Parcelable {
@Nullable PasspointConfiguration passpointConfiguration,
boolean isAppInteractionRequired,
boolean isUserInteractionRequired,
- boolean isUserAllowedToManuallyConnect,
- int suggestorUid, @NonNull String suggestorPackageName) {
+ boolean isUserAllowedToManuallyConnect) {
checkNotNull(networkConfiguration);
- checkNotNull(suggestorPackageName);
this.wifiConfiguration = networkConfiguration;
this.passpointConfiguration = passpointConfiguration;
this.isAppInteractionRequired = isAppInteractionRequired;
this.isUserInteractionRequired = isUserInteractionRequired;
this.isUserAllowedToManuallyConnect = isUserAllowedToManuallyConnect;
- this.suggestorUid = suggestorUid;
- this.suggestorPackageName = suggestorPackageName;
}
public static final @NonNull Creator<WifiNetworkSuggestion> CREATOR =
@@ -651,9 +627,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
in.readParcelable(null), // PasspointConfiguration
in.readBoolean(), // isAppInteractionRequired
in.readBoolean(), // isUserInteractionRequired
- in.readBoolean(), // isSharedCredentialWithUser
- in.readInt(), // suggestorUid
- in.readString() // suggestorPackageName
+ in.readBoolean() // isSharedCredentialWithUser
);
}
@@ -675,15 +649,12 @@ public final class WifiNetworkSuggestion implements Parcelable {
dest.writeBoolean(isAppInteractionRequired);
dest.writeBoolean(isUserInteractionRequired);
dest.writeBoolean(isUserAllowedToManuallyConnect);
- dest.writeInt(suggestorUid);
- dest.writeString(suggestorPackageName);
}
@Override
public int hashCode() {
return Objects.hash(wifiConfiguration.SSID, wifiConfiguration.BSSID,
- wifiConfiguration.allowedKeyManagement, wifiConfiguration.FQDN,
- suggestorUid, suggestorPackageName);
+ wifiConfiguration.allowedKeyManagement, wifiConfiguration.FQDN);
}
/**
@@ -706,23 +677,19 @@ public final class WifiNetworkSuggestion implements Parcelable {
&& TextUtils.equals(this.wifiConfiguration.BSSID, lhs.wifiConfiguration.BSSID)
&& Objects.equals(this.wifiConfiguration.allowedKeyManagement,
lhs.wifiConfiguration.allowedKeyManagement)
- && TextUtils.equals(this.wifiConfiguration.FQDN, lhs.wifiConfiguration.FQDN)
- && this.suggestorUid == lhs.suggestorUid
- && TextUtils.equals(this.suggestorPackageName, lhs.suggestorPackageName);
+ && TextUtils.equals(this.wifiConfiguration.FQDN, lhs.wifiConfiguration.FQDN);
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder("WifiNetworkSuggestion [")
- .append(", SSID=").append(wifiConfiguration.SSID)
+ StringBuilder sb = new StringBuilder("WifiNetworkSuggestion[ ")
+ .append("SSID=").append(wifiConfiguration.SSID)
.append(", BSSID=").append(wifiConfiguration.BSSID)
.append(", FQDN=").append(wifiConfiguration.FQDN)
.append(", isAppInteractionRequired=").append(isAppInteractionRequired)
.append(", isUserInteractionRequired=").append(isUserInteractionRequired)
.append(", isUserAllowedToManuallyConnect=").append(isUserAllowedToManuallyConnect)
- .append(", suggestorUid=").append(suggestorUid)
- .append(", suggestorPackageName=").append(suggestorPackageName)
- .append("]");
+ .append(" ]");
return sb.toString();
}
}
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 65a6c4d051cd..81bf81e40199 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -19,6 +19,7 @@ package android.net.wifi.aware;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
@@ -396,6 +397,17 @@ public class WifiAwareManager {
}
/** @hide */
+ @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
+ public void requestMacAddresses(int uid, List<Integer> peerIds,
+ IWifiAwareMacAddressProvider callback) {
+ try {
+ mService.requestMacAddresses(uid, peerIds, callback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** @hide */
public NetworkSpecifier createNetworkSpecifier(int clientId, int role, int sessionId,
@NonNull PeerHandle peerHandle, @Nullable byte[] pmk, @Nullable String passphrase) {
if (VDBG) {
diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java
index 367cfa069e74..2c27037d29aa 100644
--- a/wifi/java/com/android/server/wifi/BaseWifiService.java
+++ b/wifi/java/com/android/server/wifi/BaseWifiService.java
@@ -76,11 +76,14 @@ public class BaseWifiService extends IWifiManager.Stub {
throw new UnsupportedOperationException();
}
- @Override
+ /** @deprecated use {@link #getWifiActivityEnergyInfoAsync} instead */
+ @Deprecated
public WifiActivityEnergyInfo reportActivityInfo() {
throw new UnsupportedOperationException();
}
+ /** @deprecated use {@link #getWifiActivityEnergyInfoAsync} instead */
+ @Deprecated
public void requestActivityInfo(ResultReceiver result) {
throw new UnsupportedOperationException();
}
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index de4514997b1c..f92d38c982b8 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -161,7 +161,7 @@ public class WifiManagerTest {
mRunnable.run();
}
};
- mWifiActivityEnergyInfo = new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0, 0);
+ mWifiActivityEnergyInfo = new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0);
}
/**
@@ -1708,18 +1708,6 @@ public class WifiManagerTest {
}
/**
- * Test behavior of {@link WifiManager#getControllerActivityEnergyInfo()}
- */
- @Test
- public void testGetControllerActivityEnergyInfo() throws Exception {
- WifiActivityEnergyInfo activityEnergyInfo =
- new WifiActivityEnergyInfo(5, 3, 3, 5, 5, 5, 5);
- when(mWifiService.reportActivityInfo()).thenReturn(activityEnergyInfo);
-
- assertEquals(activityEnergyInfo, mWifiManager.getControllerActivityEnergyInfo());
- }
-
- /**
* Tests that passing a null Executor to {@link WifiManager#getWifiActivityEnergyInfoAsync}
* throws an exception.
*/
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index 8a5a0fd6805b..04aaa0bbcad0 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -22,7 +22,6 @@ import android.net.MacAddress;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.PasspointTestUtils;
import android.os.Parcel;
-import android.os.Process;
import androidx.test.filters.SmallTest;
@@ -35,8 +34,6 @@ import org.junit.Test;
public class WifiNetworkSuggestionTest {
private static final int TEST_UID = 45677;
private static final int TEST_UID_OTHER = 45673;
- private static final String TEST_PACKAGE_NAME = "com.test.packagename";
- private static final String TEST_PACKAGE_NAME_OTHER = "com.test.packagenameother";
private static final String TEST_SSID = "\"Test123\"";
private static final String TEST_BSSID = "12:12:12:12:12:12";
private static final String TEST_SSID_1 = "\"Test1234\"";
@@ -55,7 +52,6 @@ public class WifiNetworkSuggestionTest {
.setIsAppInteractionRequired(true)
.build();
- assertEquals(Process.myUid(), suggestion.suggestorUid);
assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
.get(WifiConfiguration.KeyMgmt.NONE));
@@ -448,7 +444,7 @@ public class WifiNetworkSuggestionTest {
configuration.BSSID = TEST_BSSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion(
- configuration, null, false, true, true, TEST_UID, TEST_PACKAGE_NAME);
+ configuration, null, false, true, true);
Parcel parcelW = Parcel.obtain();
suggestion.writeToParcel(parcelW, 0);
@@ -515,16 +511,14 @@ public class WifiNetworkSuggestionTest {
configuration.BSSID = TEST_BSSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, true, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration, null, true, false, true);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID;
configuration1.BSSID = TEST_BSSID;
configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, true, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration1, null, false, true, true);
assertEquals(suggestion, suggestion1);
assertEquals(suggestion.hashCode(), suggestion1.hashCode());
@@ -540,15 +534,13 @@ public class WifiNetworkSuggestionTest {
configuration.SSID = TEST_SSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, false, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration, null, false, false, true);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID_1;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration1, null, false, false, true);
assertNotEquals(suggestion, suggestion1);
}
@@ -564,15 +556,13 @@ public class WifiNetworkSuggestionTest {
configuration.BSSID = TEST_BSSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, false, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration, null, false, false, true);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID;
configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration1, null, false, false, true);
assertNotEquals(suggestion, suggestion1);
}
@@ -587,57 +577,18 @@ public class WifiNetworkSuggestionTest {
configuration.SSID = TEST_SSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, false, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration, null, false, false, true);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID;
configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration1, null, false, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
+ new WifiNetworkSuggestion(configuration1, null, false, false, true);
assertNotEquals(suggestion, suggestion1);
}
/**
- * Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same
- * SSID, BSSID and key mgmt, but different UID.
- */
- @Test
- public void testWifiNetworkSuggestionEqualsFailsWhenUidIsDifferent() {
- WifiConfiguration configuration = new WifiConfiguration();
- configuration.SSID = TEST_SSID;
- configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
- WifiNetworkSuggestion suggestion =
- new WifiNetworkSuggestion(configuration, null, false, false, true, TEST_UID,
- TEST_PACKAGE_NAME);
-
- WifiNetworkSuggestion suggestion1 =
- new WifiNetworkSuggestion(configuration, null, false, false, true, TEST_UID_OTHER,
- TEST_PACKAGE_NAME);
-
- assertNotEquals(suggestion, suggestion1);
- }
-
- /**
- * Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same
- * SSID, BSSID and key mgmt, but different package name.
- */
- @Test
- public void testWifiNetworkSuggestionEqualsFailsWhenPackageNameIsDifferent() {
- WifiConfiguration configuration = new WifiConfiguration();
- configuration.SSID = TEST_SSID;
- configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
- WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion(
- configuration, null, false, false, true, TEST_UID, TEST_PACKAGE_NAME);
-
- WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion(
- configuration, null, false, false, true, TEST_UID, TEST_PACKAGE_NAME_OTHER);
-
- assertNotEquals(suggestion, suggestion1);
- }
- /**
* Check NetworkSuggestion equals returns {@code true} for 2 Passpoint network suggestions with
* same FQDN.
*/