Merge "Catch unbinding errors" into pi-dev
diff --git a/api/current.txt b/api/current.txt
index 0fcf929..d0eee5c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6468,7 +6468,6 @@
method public java.lang.CharSequence getOrganizationName(android.content.ComponentName);
method public java.util.List<android.telephony.data.ApnSetting> getOverrideApns(android.content.ComponentName);
method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
- method public java.lang.String getPasswordBlacklistName(android.content.ComponentName);
method public long getPasswordExpiration(android.content.ComponentName);
method public long getPasswordExpirationTimeout(android.content.ComponentName);
method public int getPasswordHistoryLength(android.content.ComponentName);
@@ -6577,7 +6576,6 @@
method public void setOrganizationName(android.content.ComponentName, java.lang.CharSequence);
method public void setOverrideApnsEnabled(android.content.ComponentName, boolean);
method public java.lang.String[] setPackagesSuspended(android.content.ComponentName, java.lang.String[], boolean);
- method public boolean setPasswordBlacklist(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>);
method public void setPasswordExpirationTimeout(android.content.ComponentName, long);
method public void setPasswordHistoryLength(android.content.ComponentName, int);
method public void setPasswordMinimumLength(android.content.ComponentName, int);
@@ -27242,6 +27240,8 @@
public class NetworkRequest implements android.os.Parcelable {
method public int describeContents();
+ method public boolean hasCapability(int);
+ method public boolean hasTransport(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.NetworkRequest> CREATOR;
}
diff --git a/api/system-current.txt b/api/system-current.txt
index ed763ba..1284de88 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3105,6 +3105,10 @@
field public static final int ERROR_INVALID_NETWORK = 1; // 0x1
}
+ public final class NetworkCapabilities implements android.os.Parcelable {
+ field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16
+ }
+
public class NetworkKey implements android.os.Parcelable {
ctor public NetworkKey(android.net.WifiKey);
method public int describeContents();
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 3b57d34..d964651 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -319,8 +319,10 @@
index++; // look at the next file.
}
VLOG("GZipSection is using file %s, fd=%d", mFilenames[index], fd.get());
- if (fd.get() == -1) return -1;
-
+ if (fd.get() == -1) {
+ ALOGW("GZipSection %s can't open all the files", this->name.string());
+ return NO_ERROR; // e.g. LAST_KMSG will reach here in user build.
+ }
FdBuffer buffer;
Fpipe p2cPipe;
Fpipe c2pPipe;
diff --git a/cmds/incidentd/tests/PrivacyBuffer_test.cpp b/cmds/incidentd/tests/PrivacyBuffer_test.cpp
index 5edc0c7..d129269 100644
--- a/cmds/incidentd/tests/PrivacyBuffer_test.cpp
+++ b/cmds/incidentd/tests/PrivacyBuffer_test.cpp
@@ -38,7 +38,7 @@
const uint8_t MESSAGE_TYPE = 11;
const string STRING_FIELD_0 = "\x02\viamtestdata";
const string VARINT_FIELD_1 = "\x08\x96\x01"; // 150
-const string STRING_FIELD_2 = "\x12\vwhatthefuck";
+const string STRING_FIELD_2 = "\x12\vandroidwins";
const string FIX64_FIELD_3 = "\x19\xff\xff\xff\xff\xff\xff\xff\xff"; // -1
const string FIX32_FIELD_4 = "\x25\xff\xff\xff\xff"; // -1
const string MESSAGE_FIELD_5 = "\x2a\x10" + VARINT_FIELD_1 + STRING_FIELD_2;
@@ -274,4 +274,4 @@
autoMsg->children = list;
string expected = "\x2a\xd" + STRING_FIELD_2;
assertStripByFields(DEST_AUTOMATIC, expected, 1, autoMsg);
-}
\ No newline at end of file
+}
diff --git a/cmds/incidentd/tests/Section_test.cpp b/cmds/incidentd/tests/Section_test.cpp
index f93839b..2f6698b 100644
--- a/cmds/incidentd/tests/Section_test.cpp
+++ b/cmds/incidentd/tests/Section_test.cpp
@@ -19,6 +19,7 @@
#include <android-base/file.h>
#include <android-base/test_utils.h>
#include <android/os/IncidentReportArgs.h>
+#include <android/util/protobuf.h>
#include <frameworks/base/libs/incident/proto/android/os/header.pb.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -31,12 +32,13 @@
const int QUICK_TIMEOUT_MS = 100;
const string VARINT_FIELD_1 = "\x08\x96\x01"; // 150
-const string STRING_FIELD_2 = "\x12\vwhatthefuck";
+const string STRING_FIELD_2 = "\x12\vandroidwins";
const string FIX64_FIELD_3 = "\x19\xff\xff\xff\xff\xff\xff\xff\xff"; // -1
using namespace android::base;
using namespace android::binder;
using namespace android::os;
+using namespace android::util;
using namespace std;
using ::testing::StrEq;
using ::testing::Test;
@@ -154,17 +156,26 @@
requests.setMainDest(android::os::DEST_LOCAL);
ASSERT_EQ(NO_ERROR, gs.Execute(&requests));
- std::string expect, gzFile, actual;
+ std::string expected, gzFile, actual;
ASSERT_TRUE(ReadFileToString(testGzFile, &gzFile));
ASSERT_TRUE(ReadFileToString(tf.path, &actual));
- expect = "\x2\xC6\x6\n\"" + testFile + "\x12\x9F\x6" + gzFile;
- EXPECT_THAT(actual, StrEq(expect));
+ // generates the expected protobuf result.
+ size_t fileLen = testFile.size();
+ size_t totalLen = 1 + get_varint_size(fileLen) + fileLen + 3 + gzFile.size();
+ uint8_t header[20];
+ header[0] = '\x2'; // header 0 << 3 + 2
+ uint8_t* ptr = write_raw_varint(header + 1, totalLen);
+ *ptr = '\n'; // header 1 << 3 + 2
+ ptr = write_raw_varint(++ptr, fileLen);
+ expected.assign((const char*)header, ptr - header);
+ expected += testFile + "\x12\x9F\x6" + gzFile;
+ EXPECT_THAT(actual, StrEq(expected));
}
TEST_F(SectionTest, GZipSectionNoFileFound) {
GZipSection gs(NOOP_PARSER, "/tmp/nonexist1", "/tmp/nonexist2", NULL);
requests.setMainFd(STDOUT_FILENO);
- ASSERT_EQ(-1, gs.Execute(&requests));
+ ASSERT_EQ(NO_ERROR, gs.Execute(&requests));
}
TEST_F(SectionTest, CommandSectionConstructor) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3c6f135..b64aae5 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2747,110 +2747,6 @@
}
/**
- * The maximum number of characters allowed in the password blacklist.
- */
- private static final int PASSWORD_BLACKLIST_CHARACTER_LIMIT = 128 * 1000;
-
- /**
- * Throws an exception if the password blacklist is too large.
- *
- * @hide
- */
- public static void enforcePasswordBlacklistSize(List<String> blacklist) {
- if (blacklist == null) {
- return;
- }
- long characterCount = 0;
- for (final String item : blacklist) {
- characterCount += item.length();
- }
- if (characterCount > PASSWORD_BLACKLIST_CHARACTER_LIMIT) {
- throw new IllegalArgumentException("128 thousand blacklist character limit exceeded by "
- + (characterCount - PASSWORD_BLACKLIST_CHARACTER_LIMIT) + " characters");
- }
- }
-
- /**
- * Called by an application that is administering the device to blacklist passwords.
- * <p>
- * Any blacklisted password or PIN is prevented from being enrolled by the user or the admin.
- * Note that the match against the blacklist is case insensitive. The blacklist applies for all
- * password qualities requested by {@link #setPasswordQuality} however it is not taken into
- * consideration by {@link #isActivePasswordSufficient}.
- * <p>
- * The blacklist can be cleared by passing {@code null} or an empty list. The blacklist is
- * given a name that is used to track which blacklist is currently set by calling {@link
- * #getPasswordBlacklistName}. If the blacklist is being cleared, the name is ignored and {@link
- * #getPasswordBlacklistName} will return {@code null}. The name can only be {@code null} when
- * the blacklist is being cleared.
- * <p>
- * The blacklist is limited to a total of 128 thousand characters rather than limiting to a
- * number of entries.
- * <p>
- * This method can be called on the {@link DevicePolicyManager} instance returned by
- * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent
- * profile.
- *
- * @param admin the {@link DeviceAdminReceiver} this request is associated with
- * @param name name to associate with the blacklist
- * @param blacklist list of passwords to blacklist or {@code null} to clear the blacklist
- * @return whether the new blacklist was successfully installed
- * @throws SecurityException if {@code admin} is not a device or profile owner
- * @throws IllegalArgumentException if the blacklist surpasses the character limit
- * @throws NullPointerException if {@code name} is {@code null} when setting a non-empty list
- *
- * @see #getPasswordBlacklistName
- * @see #isActivePasswordSufficient
- * @see #resetPasswordWithToken
- */
- public boolean setPasswordBlacklist(@NonNull ComponentName admin, @Nullable String name,
- @Nullable List<String> blacklist) {
- enforcePasswordBlacklistSize(blacklist);
-
- try {
- return mService.setPasswordBlacklist(admin, name, blacklist, mParentInstance);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- }
-
- /**
- * Get the name of the password blacklist set by the given admin.
- *
- * @param admin the {@link DeviceAdminReceiver} this request is associated with
- * @return the name of the blacklist or {@code null} if no blacklist is set
- *
- * @see #setPasswordBlacklist
- */
- public @Nullable String getPasswordBlacklistName(@NonNull ComponentName admin) {
- try {
- return mService.getPasswordBlacklistName(admin, myUserId(), mParentInstance);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- }
-
- /**
- * Test if a given password is blacklisted.
- *
- * @param userId the user to valiate for
- * @param password the password to check against the blacklist
- * @return whether the password is blacklisted
- *
- * @see #setPasswordBlacklist
- *
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.TEST_BLACKLISTED_PASSWORD)
- public boolean isPasswordBlacklisted(@UserIdInt int userId, @NonNull String password) {
- try {
- return mService.isPasswordBlacklisted(userId, password);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
- }
-
- /**
* Determine whether the current password the user has set is sufficient to meet the policy
* requirements (e.g. quality, minimum length) that have been requested by the admins of this
* user and its participating profiles. Restrictions on profiles that have a separate challenge
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 4b39a9a..37508cd 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -79,10 +79,6 @@
long getPasswordExpiration(in ComponentName who, int userHandle, boolean parent);
- boolean setPasswordBlacklist(in ComponentName who, String name, in List<String> blacklist, boolean parent);
- String getPasswordBlacklistName(in ComponentName who, int userId, boolean parent);
- boolean isPasswordBlacklisted(int userId, String password);
-
boolean isActivePasswordSufficient(int userHandle, boolean parent);
boolean isProfileActivePasswordSufficientForParent(int userHandle);
boolean isUsingUnifiedPassword(in ComponentName admin);
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index 1afe53d..88b198b 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -81,6 +81,17 @@
* An activity can be statically linked to a slice uri by including a meta-data item
* for this key that contains a valid slice uri for the same application declaring
* the activity.
+ *
+ * <pre class="prettyprint">
+ * {@literal
+ * <activity android:name="com.example.mypkg.MyActivity">
+ * <meta-data android:name="android.metadata.SLICE_URI"
+ * android:value="content://com.example.mypkg/main_slice" />
+ * </activity>}
+ * </pre>
+ *
+ * @see #mapIntentToUri(Intent)
+ * @see SliceProvider#onMapIntentToUri(Intent)
*/
public static final String SLICE_METADATA_KEY = "android.metadata.SLICE_URI";
@@ -257,16 +268,17 @@
* <p>
* This goes through a several stage resolution process to determine if any slice
* can represent this intent.
- * - If the intent contains data that {@link ContentResolver#getType} is
- * {@link SliceProvider#SLICE_TYPE} then the data will be returned.
- * - If the intent with {@link #CATEGORY_SLICE} added resolves to a provider, then
+ * <ol>
+ * <li> If the intent contains data that {@link ContentResolver#getType} is
+ * {@link SliceProvider#SLICE_TYPE} then the data will be returned.</li>
+ * <li>If the intent with {@link #CATEGORY_SLICE} added resolves to a provider, then
* the provider will be asked to {@link SliceProvider#onMapIntentToUri} and that result
- * will be returned.
- * - Lastly, if the intent explicitly points at an activity, and that activity has
+ * will be returned.</li>
+ * <li>Lastly, if the intent explicitly points at an activity, and that activity has
* meta-data for key {@link #SLICE_METADATA_KEY}, then the Uri specified there will be
- * returned.
- * - If no slice is found, then {@code null} is returned.
- *
+ * returned.</li>
+ * <li>If no slice is found, then {@code null} is returned.</li>
+ * </ol>
* @param intent The intent associated with a slice.
* @return The Slice Uri provided by the app or null if none exists.
* @see Slice
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index ff5714b..374b3ab 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.IntDef;
+import android.annotation.SystemApi;
import android.net.ConnectivityManager.NetworkCallback;
import android.os.Parcel;
import android.os.Parcelable;
@@ -276,6 +277,7 @@
* this network can be used by system apps to upload telemetry data.
* @hide
*/
+ @SystemApi
public static final int NET_CAPABILITY_OEM_PAID = 22;
private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 4f92fa6..caefd89 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -17,6 +17,8 @@
package android.net;
import android.annotation.NonNull;
+import android.net.NetworkCapabilities.NetCapability;
+import android.net.NetworkCapabilities.Transport;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
@@ -427,6 +429,20 @@
return type == Type.BACKGROUND_REQUEST;
}
+ /**
+ * @see Builder#addCapability(int)
+ */
+ public boolean hasCapability(@NetCapability int capability) {
+ return networkCapabilities.hasCapability(capability);
+ }
+
+ /**
+ * @see Builder#addTransportType(int)
+ */
+ public boolean hasTransport(@Transport int transportType) {
+ return networkCapabilities.hasTransport(transportType);
+ }
+
public String toString() {
return "NetworkRequest [ " + type + " id=" + requestId +
(legacyType != ConnectivityManager.TYPE_NONE ? ", legacyType=" + legacyType : "") +
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b7f6cdef..b0367dc 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11061,7 +11061,14 @@
*/
public static final String LOW_POWER_MODE_TRIGGER_LEVEL_MAX = "low_power_trigger_level_max";
- /**
+ /**
+ * See com.android.settingslib.fuelgauge.BatterySaverUtils.
+ * @hide
+ */
+ public static final String LOW_POWER_MODE_SUGGESTION_PARAMS =
+ "low_power_mode_suggestion_params";
+
+ /**
* If not 0, the activity manager will aggressively finish activities and
* processes as soon as they are no longer needed. If 0, the normal
* extended lifetime is used.
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 1d13335..f4dcce1 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -75,6 +75,7 @@
public static final int KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506;
public static final int KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED = KM_BOOL | 507;
public static final int KM_TAG_TRUSTED_CONFIRMATION_REQUIRED = KM_BOOL | 508;
+ public static final int KM_TAG_UNLOCKED_DEVICE_REQUIRED = KM_BOOL | 509;
public static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600;
public static final int KM_TAG_APPLICATION_ID = KM_BYTES | 601;
@@ -216,6 +217,7 @@
public static final int KM_ERROR_MISSING_MIN_MAC_LENGTH = -58;
public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = -59;
public static final int KM_ERROR_CANNOT_ATTEST_IDS = -66;
+ public static final int KM_ERROR_DEVICE_LOCKED = -72;
public static final int KM_ERROR_UNIMPLEMENTED = -100;
public static final int KM_ERROR_VERSION_MISMATCH = -101;
public static final int KM_ERROR_UNKNOWN_ERROR = -1000;
@@ -262,6 +264,7 @@
sErrorCodeToString.put(KM_ERROR_INVALID_MAC_LENGTH,
"Invalid MAC or authentication tag length");
sErrorCodeToString.put(KM_ERROR_CANNOT_ATTEST_IDS, "Unable to attest device ids");
+ sErrorCodeToString.put(KM_ERROR_DEVICE_LOCKED, "Device locked");
sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented");
sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error");
}
diff --git a/core/java/android/service/notification/ScheduleCalendar.java b/core/java/android/service/notification/ScheduleCalendar.java
index 8a7ff4d..0128710 100644
--- a/core/java/android/service/notification/ScheduleCalendar.java
+++ b/core/java/android/service/notification/ScheduleCalendar.java
@@ -144,7 +144,8 @@
}
return mSchedule.exitAtAlarm
&& mSchedule.nextAlarm != 0
- && time >= mSchedule.nextAlarm;
+ && time >= mSchedule.nextAlarm
+ && isInSchedule(mSchedule.nextAlarm);
}
private boolean isInSchedule(int daysOffset, long time, long start, long end) {
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 0fea0dc..ea0b825 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -175,9 +175,9 @@
];
optional GZippedFileProto last_kmsg = 2007 [
- (section).type = SECTION_NONE, // disable until selinux permission is gained
+ (section).type = SECTION_GZIP,
(section).args = "/sys/fs/pstore/console-ramoops /sys/fs/pstore/console-ramoops-0 /proc/last_kmsg",
- (privacy).dest = DEST_AUTOMATIC
+ (privacy).dest = DEST_EXPLICIT
];
// System Services
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 4b9465d..dfc99f6 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -267,6 +267,7 @@
Settings.Global.LOW_POWER_MODE,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
Settings.Global.LOW_POWER_MODE_STICKY,
+ Settings.Global.LOW_POWER_MODE_SUGGESTION_PARAMS,
Settings.Global.LTE_SERVICE_FORCED,
Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
Settings.Global.MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY,
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 1e2ebf8..81644eb 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -16,6 +16,7 @@
package android.security;
+import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.Application;
import android.app.KeyguardManager;
@@ -279,7 +280,7 @@
/**
* Attempt to lock the keystore for {@code user}.
*
- * @param user Android user to lock.
+ * @param userId Android user to lock.
* @return whether {@code user}'s keystore was locked.
*/
public boolean lock(int userId) {
@@ -300,7 +301,7 @@
* This is required before keystore entries created with FLAG_ENCRYPTED can be accessed or
* created.
*
- * @param user Android user ID to operate on
+ * @param userId Android user ID to operate on
* @param password user's keystore password. Should be the most recent value passed to
* {@link #onUserPasswordChanged} for the user.
*
@@ -546,6 +547,9 @@
try {
args = args != null ? args : new KeymasterArguments();
entropy = entropy != null ? entropy : new byte[0];
+ if (!args.containsTag(KeymasterDefs.KM_TAG_USER_ID)) {
+ args.addUnsignedInt(KeymasterDefs.KM_TAG_USER_ID, ActivityManager.getCurrentUser());
+ }
return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 4b9f3c80..5d596cb 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -266,6 +266,7 @@
private final boolean mInvalidatedByBiometricEnrollment;
private final boolean mIsStrongBoxBacked;
private final boolean mUserConfirmationRequired;
+ private final boolean mUnlockedDeviceRequired;
/**
* @hide should be built with Builder
@@ -296,7 +297,8 @@
boolean userAuthenticationValidWhileOnBody,
boolean invalidatedByBiometricEnrollment,
boolean isStrongBoxBacked,
- boolean userConfirmationRequired) {
+ boolean userConfirmationRequired,
+ boolean unlockedDeviceRequired) {
if (TextUtils.isEmpty(keyStoreAlias)) {
throw new IllegalArgumentException("keyStoreAlias must not be empty");
}
@@ -345,6 +347,7 @@
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
mIsStrongBoxBacked = isStrongBoxBacked;
mUserConfirmationRequired = userConfirmationRequired;
+ mUnlockedDeviceRequired = unlockedDeviceRequired;
}
/**
@@ -670,6 +673,15 @@
}
/**
+ * @hide Returns {@code true} if the key cannot be used unless the device screen is unlocked.
+ *
+ * @see Builder#setUnlockedDeviceRequired(boolean)
+ */
+ public boolean isUnlockedDeviceRequired() {
+ return mUnlockedDeviceRequired;
+ }
+
+ /**
* @hide
*/
public long getBoundToSpecificSecureUserId() {
@@ -707,6 +719,7 @@
private boolean mInvalidatedByBiometricEnrollment = true;
private boolean mIsStrongBoxBacked = false;
private boolean mUserConfirmationRequired;
+ private boolean mUnlockedDeviceRequired = false;
/**
* Creates a new instance of the {@code Builder}.
@@ -1275,6 +1288,18 @@
}
/**
+ * @hide Sets whether the keystore requires the screen to be unlocked before allowing decryption
+ * using this key. If this is set to {@code true}, any attempt to decrypt using this key
+ * while the screen is locked will fail. A locked device requires a PIN, password,
+ * fingerprint, or other trusted factor to access.
+ */
+ @NonNull
+ public Builder setUnlockedDeviceRequired(boolean unlockedDeviceRequired) {
+ mUnlockedDeviceRequired = unlockedDeviceRequired;
+ return this;
+ }
+
+ /**
* Builds an instance of {@code KeyGenParameterSpec}.
*/
@NonNull
@@ -1305,7 +1330,8 @@
mUserAuthenticationValidWhileOnBody,
mInvalidatedByBiometricEnrollment,
mIsStrongBoxBacked,
- mUserConfirmationRequired);
+ mUserConfirmationRequired,
+ mUnlockedDeviceRequired);
}
}
}
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 95eeec7..cc7870c 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -224,12 +224,13 @@
private final boolean mRandomizedEncryptionRequired;
private final boolean mUserAuthenticationRequired;
private final int mUserAuthenticationValidityDurationSeconds;
- private final boolean mTrustedUserPresenceRequred;
+ private final boolean mTrustedUserPresenceRequired;
private final boolean mUserAuthenticationValidWhileOnBody;
private final boolean mInvalidatedByBiometricEnrollment;
private final long mBoundToSecureUserId;
private final boolean mCriticalToDeviceEncryption;
private final boolean mUserConfirmationRequired;
+ private final boolean mUnlockedDeviceRequired;
private KeyProtection(
Date keyValidityStart,
@@ -243,12 +244,13 @@
boolean randomizedEncryptionRequired,
boolean userAuthenticationRequired,
int userAuthenticationValidityDurationSeconds,
- boolean trustedUserPresenceRequred,
+ boolean trustedUserPresenceRequired,
boolean userAuthenticationValidWhileOnBody,
boolean invalidatedByBiometricEnrollment,
long boundToSecureUserId,
boolean criticalToDeviceEncryption,
- boolean userConfirmationRequired) {
+ boolean userConfirmationRequired,
+ boolean unlockedDeviceRequired) {
mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
@@ -262,12 +264,13 @@
mRandomizedEncryptionRequired = randomizedEncryptionRequired;
mUserAuthenticationRequired = userAuthenticationRequired;
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
- mTrustedUserPresenceRequred = trustedUserPresenceRequred;
+ mTrustedUserPresenceRequired = trustedUserPresenceRequired;
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
mBoundToSecureUserId = boundToSecureUserId;
mCriticalToDeviceEncryption = criticalToDeviceEncryption;
mUserConfirmationRequired = userConfirmationRequired;
+ mUnlockedDeviceRequired = unlockedDeviceRequired;
}
/**
@@ -444,7 +447,7 @@
* been performed between the {@code Signature.initSign()} and {@code Signature.sign()} calls.
*/
public boolean isTrustedUserPresenceRequired() {
- return mTrustedUserPresenceRequred;
+ return mTrustedUserPresenceRequired;
}
/**
@@ -505,6 +508,15 @@
}
/**
+ * @hide Returns {@code true} if the key cannot be used unless the device screen is unlocked.
+ *
+ * @see Builder#setUnlockedDeviceRequired(boolean)
+ */
+ public boolean isUnlockedDeviceRequired() {
+ return mUnlockedDeviceRequired;
+ }
+
+ /**
* Builder of {@link KeyProtection} instances.
*/
public final static class Builder {
@@ -524,6 +536,8 @@
private boolean mUserAuthenticationValidWhileOnBody;
private boolean mInvalidatedByBiometricEnrollment = true;
private boolean mUserConfirmationRequired;
+ private boolean mUnlockedDeviceRequired = false;
+
private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID;
private boolean mCriticalToDeviceEncryption = false;
@@ -914,6 +928,18 @@
}
/**
+ * @hide Sets whether the keystore requires the screen to be unlocked before allowing decryption
+ * using this key. If this is set to {@code true}, any attempt to decrypt using this key
+ * while the screen is locked will fail. A locked device requires a PIN, password,
+ * fingerprint, or other trusted factor to access.
+ */
+ @NonNull
+ public Builder setUnlockedDeviceRequired(boolean unlockedDeviceRequired) {
+ mUnlockedDeviceRequired = unlockedDeviceRequired;
+ return this;
+ }
+
+ /**
* Builds an instance of {@link KeyProtection}.
*
* @throws IllegalArgumentException if a required field is missing
@@ -937,7 +963,8 @@
mInvalidatedByBiometricEnrollment,
mBoundToSecureUserId,
mCriticalToDeviceEncryption,
- mUserConfirmationRequired);
+ mUserConfirmationRequired,
+ mUnlockedDeviceRequired);
}
}
}
diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java
index 0ef08f2..6e50121 100644
--- a/keystore/java/android/security/keystore/KeymasterUtils.java
+++ b/keystore/java/android/security/keystore/KeymasterUtils.java
@@ -16,9 +16,8 @@
package android.security.keystore;
-import android.util.Log;
+import android.app.ActivityManager;
import android.hardware.fingerprint.FingerprintManager;
-import android.os.UserHandle;
import android.security.GateKeeper;
import android.security.KeyStore;
import android.security.keymaster.KeymasterArguments;
@@ -101,8 +100,9 @@
* state (e.g., secure lock screen not set up) for generating or importing keys that
* require user authentication.
*/
- public static void addUserAuthArgs(KeymasterArguments args,
- UserAuthArgs spec) {
+ public static void addUserAuthArgs(KeymasterArguments args, UserAuthArgs spec) {
+ args.addUnsignedInt(KeymasterDefs.KM_TAG_USER_ID, ActivityManager.getCurrentUser());
+
if (spec.isUserConfirmationRequired()) {
args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED);
}
@@ -111,6 +111,10 @@
args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED);
}
+ if (spec.isUnlockedDeviceRequired()) {
+ args.addBoolean(KeymasterDefs.KM_TAG_UNLOCKED_DEVICE_REQUIRED);
+ }
+
if (!spec.isUserAuthenticationRequired()) {
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
return;
diff --git a/keystore/java/android/security/keystore/UserAuthArgs.java b/keystore/java/android/security/keystore/UserAuthArgs.java
index 1949592..ad18ff8 100644
--- a/keystore/java/android/security/keystore/UserAuthArgs.java
+++ b/keystore/java/android/security/keystore/UserAuthArgs.java
@@ -33,5 +33,6 @@
boolean isUserConfirmationRequired();
long getBoundToSpecificSecureUserId();
boolean isTrustedUserPresenceRequired();
+ boolean isUnlockedDeviceRequired();
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
index 28833a3..835ff07 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java
@@ -22,8 +22,9 @@
import android.os.PowerManager;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
-import android.support.annotation.VisibleForTesting;
+import android.util.KeyValueListParser;
import android.util.Log;
+import android.util.Slog;
/**
* Utilities related to battery saver.
@@ -48,13 +49,35 @@
public static final String ACTION_SHOW_AUTO_SAVER_SUGGESTION
= "PNW.autoSaverSuggestion";
- /**
- * We show the auto battery saver suggestion notification when the user manually enables
- * battery saver for the START_NTH time through the END_NTH time.
- * (We won't show it for END_NTH + 1 time and after.)
- */
- private static final int AUTO_SAVER_SUGGESTION_START_NTH = 4;
- private static final int AUTO_SAVER_SUGGESTION_END_NTH = 8;
+ private static class Parameters {
+ private final Context mContext;
+
+ /**
+ * We show the auto battery saver suggestion notification when the user manually enables
+ * battery saver for the START_NTH time through the END_NTH time.
+ * (We won't show it for END_NTH + 1 time and after.)
+ */
+ private static final int AUTO_SAVER_SUGGESTION_START_NTH = 4;
+ private static final int AUTO_SAVER_SUGGESTION_END_NTH = 8;
+
+ public final int startNth;
+ public final int endNth;
+
+ public Parameters(Context context) {
+ mContext = context;
+
+ final String newValue = Global.getString(mContext.getContentResolver(),
+ Global.LOW_POWER_MODE_SUGGESTION_PARAMS);
+ final KeyValueListParser parser = new KeyValueListParser(',');
+ try {
+ parser.setString(newValue);
+ } catch (IllegalArgumentException e) {
+ Slog.wtf(TAG, "Bad constants: " + newValue);
+ }
+ startNth = parser.getInt("start_nth", AUTO_SAVER_SUGGESTION_START_NTH);
+ endNth = parser.getInt("end_nth", AUTO_SAVER_SUGGESTION_END_NTH);
+ }
+ }
/**
* Enable / disable battery saver by user request.
@@ -85,8 +108,10 @@
Secure.getInt(cr, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, 0) + 1;
Secure.putInt(cr, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, count);
- if ((count >= AUTO_SAVER_SUGGESTION_START_NTH)
- && (count <= AUTO_SAVER_SUGGESTION_END_NTH)
+ final Parameters parameters = new Parameters(context);
+
+ if ((count >= parameters.startNth)
+ && (count <= parameters.endNth)
&& Global.getInt(cr, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0) == 0
&& Secure.getInt(cr,
Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION, 0) == 0) {
diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/SystemUI/res/values/dimens_car.xml
index 5679dd2..6caed61 100644
--- a/packages/SystemUI/res/values/dimens_car.xml
+++ b/packages/SystemUI/res/values/dimens_car.xml
@@ -32,6 +32,8 @@
<dimen name="car_navigation_button_width">64dp</dimen>
<dimen name="car_navigation_bar_width">760dp</dimen>
+ <dimen name="car_left_navigation_bar_width">96dp</dimen>
+ <dimen name="car_right_navigation_bar_width">96dp</dimen>
<dimen name="car_page_indicator_dot_diameter">12dp</dimen>
<dimen name="car_page_indicator_margin_bottom">24dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index e9b2be9..4074042 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1748,6 +1748,10 @@
<!-- Name of the headset in status bar [CHAR LIMIT=30] -->
<string name="headset">Headset</string>
+ <!-- Accessibility description for long click on a quick settings tile - this is used in the
+ context of the sentence "double tap and hold to _Open settings_" [CHAR LIMIT=NONE] -->
+ <string name="accessibility_long_click_tile">Open settings</string>
+
<!-- Accessibility description of headphones icon [CHAR LIMIT=NONE] -->
<string name="accessibility_status_bar_headphones">Headphones connected</string>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 2c0e95b..a61ce8c 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -29,30 +29,16 @@
import android.os.Trace;
import android.os.UserHandle;
import android.util.ArraySet;
-import android.util.TimingsTraceLog;
import android.util.Log;
+import android.util.TimingsTraceLog;
-import com.android.systemui.globalactions.GlobalActionsComponent;
-import com.android.systemui.keyboard.KeyboardUI;
-import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.media.RingtonePlayer;
-import com.android.systemui.pip.PipUI;
import com.android.systemui.plugins.OverlayPlugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.PluginManager;
-import com.android.systemui.power.PowerUI;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.shortcut.ShortcutKeyDispatcher;
-import com.android.systemui.stackdivider.Divider;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarWindowManager;
-import com.android.systemui.usb.StorageNotification;
import com.android.systemui.util.NotificationChannels;
-import com.android.systemui.util.leak.GarbageMonitor;
-import com.android.systemui.volume.VolumeUI;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@@ -99,6 +85,10 @@
mServices[i].onBootCompleted();
}
}
+
+ IntentFilter localeChangedFilter = new IntentFilter(
+ Intent.ACTION_LOCALE_CHANGED);
+ registerReceiver(mLocaleChangeReceiver, localeChangedFilter);
}
}, filter);
} else {
@@ -249,4 +239,14 @@
public SystemUI[] getServices() {
return mServices;
}
+
+ private final BroadcastReceiver mLocaleChangeReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
+ // Update names of SystemUi notification channels
+ NotificationChannels.createAll(context);
+ }
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index a9defc8..09d928f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -194,6 +194,7 @@
setClickable(state.state != Tile.STATE_UNAVAILABLE);
mIcon.setIcon(state);
setContentDescription(state.contentDescription);
+
mAccessibilityClass = state.expandedAccessibilityClassName;
if (state instanceof QSTile.BooleanState) {
boolean newState = ((BooleanState) state).value;
@@ -269,6 +270,10 @@
info.setText(label);
info.setChecked(b);
info.setCheckable(true);
+ info.addAction(
+ new AccessibilityNodeInfo.AccessibilityAction(
+ AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK.getId(),
+ getResources().getString(R.string.accessibility_long_click_tile)));
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
index 2841136..b7d501e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
@@ -46,6 +46,12 @@
}
}
+ public void removeAll() {
+ mButtonsByCategory.clear();
+ mButtonsByPackage.clear();
+ mSelectedFacetButton = null;
+ }
+
/**
* This will unselect the currently selected CarFacetButton and determine which one should be
* selected next. It does this by reading the properties on the CarFacetButton and seeing if
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index a95d0a4..3530e0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -45,6 +45,7 @@
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import java.io.FileDescriptor;
@@ -80,12 +81,16 @@
private boolean mShowRight;
private boolean mShowBottom;
private CarFacetButtonController mCarFacetButtonController;
+ private ActivityManagerWrapper mActivityManagerWrapper;
+ private DeviceProvisionedController mDeviceProvisionedController;
+ private boolean mDeviceIsProvisioned = true;
@Override
public void start() {
super.start();
mTaskStackListener = new TaskStackListenerImpl();
- ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
+ mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
+ mActivityManagerWrapper.registerTaskStackListener(mTaskStackListener);
mStackScroller.setScrollingEnabled(true);
@@ -96,12 +101,54 @@
Log.d(TAG, "Connecting to HVAC service");
Dependency.get(HvacController.class).connectToCarService();
}
+ mCarFacetButtonController = Dependency.get(CarFacetButtonController.class);
+ mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
+ mDeviceIsProvisioned = mDeviceProvisionedController.isDeviceProvisioned();
+ if (!mDeviceIsProvisioned) {
+ mDeviceProvisionedController.addCallback(
+ new DeviceProvisionedController.DeviceProvisionedListener() {
+ @Override
+ public void onDeviceProvisionedChanged() {
+ mDeviceIsProvisioned =
+ mDeviceProvisionedController.isDeviceProvisioned();
+ restartNavBars();
+ }
+ });
+ }
}
+ /**
+ * Remove all content from navbars and rebuild them. Used to allow for different nav bars
+ * before and after the device is provisioned
+ */
+ private void restartNavBars() {
+ mCarFacetButtonController.removeAll();
+ if (ENABLE_HVAC_CONNECTION) {
+ Dependency.get(HvacController.class).removeAllComponents();
+ }
+ if (mNavigationBarWindow != null) {
+ mNavigationBarWindow.removeAllViews();
+ mNavigationBarView = null;
+ }
+
+ if (mLeftNavigationBarWindow != null) {
+ mLeftNavigationBarWindow.removeAllViews();
+ mLeftNavigationBarView = null;
+ }
+
+ if (mRightNavigationBarWindow != null) {
+ mRightNavigationBarWindow.removeAllViews();
+ mRightNavigationBarView = null;
+ }
+ buildNavBarContent();
+ }
+
+
@Override
public void destroy() {
mCarBatteryController.stopListening();
mConnectedDeviceSignalController.stopListening();
+ mActivityManagerWrapper.unregisterTaskStackListener(mTaskStackListener);
if (mNavigationBarWindow != null) {
mWindowManager.removeViewImmediate(mNavigationBarWindow);
@@ -117,10 +164,10 @@
mWindowManager.removeViewImmediate(mRightNavigationBarWindow);
mRightNavigationBarView = null;
}
-
super.destroy();
}
+
@Override
protected void makeStatusBarView() {
super.makeStatusBarView();
@@ -167,129 +214,132 @@
@Override
protected void createNavigationBar() {
- mCarFacetButtonController = Dependency.get(CarFacetButtonController.class);
- if (mNavigationBarView != null) {
- return;
- }
-
mShowBottom = mContext.getResources().getBoolean(R.bool.config_enableBottomNavigationBar);
- if (mShowBottom) {
- buildBottomBar();
- }
-
- int widthForSides = mContext.getResources().getDimensionPixelSize(
- R.dimen.navigation_bar_height_car_mode);
-
-
mShowLeft = mContext.getResources().getBoolean(R.bool.config_enableLeftNavigationBar);
-
- if (mShowLeft) {
- buildLeft(widthForSides);
- }
-
mShowRight = mContext.getResources().getBoolean(R.bool.config_enableRightNavigationBar);
+ buildNavBarWindows();
+ buildNavBarContent();
+ attachNavBarWindows();
+ }
+
+ private void buildNavBarContent() {
+ if (mShowBottom) {
+ buildBottomBar((mDeviceIsProvisioned) ? R.layout.car_navigation_bar :
+ R.layout.car_navigation_bar_unprovisioned);
+ }
+
+ if (mShowLeft) {
+ buildLeft((mDeviceIsProvisioned) ? R.layout.car_left_navigation_bar :
+ R.layout.car_left_navigation_bar_unprovisioned);
+ }
+
if (mShowRight) {
- buildRight(widthForSides);
+ buildRight((mDeviceIsProvisioned) ? R.layout.car_right_navigation_bar :
+ R.layout.car_right_navigation_bar_unprovisioned);
+ }
+ }
+
+ private void buildNavBarWindows() {
+ if (mShowBottom) {
+
+ mNavigationBarWindow = (ViewGroup) View.inflate(mContext,
+ R.layout.navigation_bar_window, null);
+ }
+ if (mShowLeft) {
+ mLeftNavigationBarWindow = (ViewGroup) View.inflate(mContext,
+ R.layout.navigation_bar_window, null);
+ }
+ if (mShowRight) {
+ mRightNavigationBarWindow = (ViewGroup) View.inflate(mContext,
+ R.layout.navigation_bar_window, null);
}
}
+ private void attachNavBarWindows() {
- private void buildBottomBar() {
+ if (mShowBottom) {
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+ PixelFormat.TRANSLUCENT);
+ lp.setTitle("CarNavigationBar");
+ lp.windowAnimations = 0;
+ mWindowManager.addView(mNavigationBarWindow, lp);
+ }
+ if (mShowLeft) {
+ int width = mContext.getResources().getDimensionPixelSize(
+ R.dimen.car_left_navigation_bar_width);
+ WindowManager.LayoutParams leftlp = new WindowManager.LayoutParams(
+ width, LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+ PixelFormat.TRANSLUCENT);
+ leftlp.setTitle("LeftCarNavigationBar");
+ leftlp.windowAnimations = 0;
+ leftlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
+ leftlp.gravity = Gravity.LEFT;
+ mWindowManager.addView(mLeftNavigationBarWindow, leftlp);
+ }
+ if (mShowRight) {
+ int width = mContext.getResources().getDimensionPixelSize(
+ R.dimen.car_right_navigation_bar_width);
+ WindowManager.LayoutParams rightlp = new WindowManager.LayoutParams(
+ width, LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+ PixelFormat.TRANSLUCENT);
+ rightlp.setTitle("RightCarNavigationBar");
+ rightlp.windowAnimations = 0;
+ rightlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
+ rightlp.gravity = Gravity.RIGHT;
+ mWindowManager.addView(mRightNavigationBarWindow, rightlp);
+ }
+
+ }
+
+ private void buildBottomBar(int layout) {
// SystemUI requires that the navigation bar view have a parent. Since the regular
// StatusBar inflates navigation_bar_window as this parent view, use the same view for the
// CarNavigationBarView.
- mNavigationBarWindow = (ViewGroup) View.inflate(mContext,
- R.layout.navigation_bar_window, null);
- if (mNavigationBarWindow == null) {
- Log.e(TAG, "CarStatusBar failed inflate for R.layout.navigation_bar_window");
- }
-
-
- View.inflate(mContext, R.layout.car_navigation_bar, mNavigationBarWindow);
+ View.inflate(mContext, layout, mNavigationBarWindow);
mNavigationBarView = (CarNavigationBarView) mNavigationBarWindow.getChildAt(0);
if (mNavigationBarView == null) {
Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
throw new RuntimeException("Unable to build botom nav bar due to missing layout");
}
mNavigationBarView.setStatusBar(this);
-
-
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
- PixelFormat.TRANSLUCENT);
- lp.setTitle("CarNavigationBar");
- lp.windowAnimations = 0;
-
-
- mWindowManager.addView(mNavigationBarWindow, lp);
}
- private void buildLeft(int widthForSides) {
- mLeftNavigationBarWindow = (ViewGroup) View.inflate(mContext,
- R.layout.navigation_bar_window, null);
- if (mLeftNavigationBarWindow == null) {
- Log.e(TAG, "CarStatusBar failed inflate for R.layout.navigation_bar_window");
- }
-
- View.inflate(mContext, R.layout.car_left_navigation_bar, mLeftNavigationBarWindow);
+ private void buildLeft(int layout) {
+ View.inflate(mContext, layout, mLeftNavigationBarWindow);
mLeftNavigationBarView = (CarNavigationBarView) mLeftNavigationBarWindow.getChildAt(0);
if (mLeftNavigationBarView == null) {
Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
throw new RuntimeException("Unable to build left nav bar due to missing layout");
}
mLeftNavigationBarView.setStatusBar(this);
-
- WindowManager.LayoutParams leftlp = new WindowManager.LayoutParams(
- widthForSides, LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
- PixelFormat.TRANSLUCENT);
- leftlp.setTitle("LeftCarNavigationBar");
- leftlp.windowAnimations = 0;
- leftlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
- leftlp.gravity = Gravity.LEFT;
- mWindowManager.addView(mLeftNavigationBarWindow, leftlp);
}
- private void buildRight(int widthForSides) {
- mRightNavigationBarWindow = (ViewGroup) View.inflate(mContext,
- R.layout.navigation_bar_window, null);
- if (mRightNavigationBarWindow == null) {
- Log.e(TAG, "CarStatusBar failed inflate for R.layout.navigation_bar_window");
- }
-
- View.inflate(mContext, R.layout.car_right_navigation_bar, mRightNavigationBarWindow);
+ private void buildRight(int layout) {
+ View.inflate(mContext, layout, mRightNavigationBarWindow);
mRightNavigationBarView = (CarNavigationBarView) mRightNavigationBarWindow.getChildAt(0);
if (mRightNavigationBarView == null) {
Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
throw new RuntimeException("Unable to build right nav bar due to missing layout");
}
- mRightNavigationBarView.setStatusBar(this);
-
- WindowManager.LayoutParams rightlp = new WindowManager.LayoutParams(
- widthForSides, LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
- PixelFormat.TRANSLUCENT);
- rightlp.setTitle("RightCarNavigationBar");
- rightlp.windowAnimations = 0;
- rightlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
- rightlp.gravity = Gravity.RIGHT;
- mWindowManager.addView(mRightNavigationBarWindow, rightlp);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
index 23bf887..7d283d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
@@ -176,6 +176,14 @@
};
/**
+ * Removes all registered components. This is useful if you need to rebuild the UI since
+ * components self register.
+ */
+ public void removeAllComponents() {
+ mTempComponents.clear();
+ }
+
+ /**
* Key for storing {@link TemperatureView}s in a hash map
*/
private static class HvacKey {
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index 1cbdfe8..7a9cdfd 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -39,8 +39,7 @@
public static String BATTERY = "BAT";
public static String HINTS = "HNT";
- @VisibleForTesting
- static void createAll(Context context) {
+ public static void createAll(Context context) {
final NotificationManager nm = context.getSystemService(NotificationManager.class);
final NotificationChannel batteryChannel = new NotificationChannel(BATTERY,
context.getString(R.string.notification_channel_battery),
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 31b0461..f31ca0a 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -182,6 +182,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.BackgroundThread;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.util.ArrayUtils;
@@ -898,6 +899,8 @@
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) {
+ // update system notification channels
+ SystemNotificationChannels.createAll(context);
mZenModeHelper.updateDefaultZenRules();
mRankingHelper.onLocaleChanged(context, ActivityManager.getCurrentUser());
}
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index 941cd44..e56caf8 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -19,6 +19,8 @@
import android.app.ActivityManager;
import android.content.Context;
import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.security.IKeystoreService;
import android.util.Slog;
import com.android.internal.policy.IKeyguardService;
@@ -51,11 +53,16 @@
private final LockPatternUtils mLockPatternUtils;
private final StateCallback mCallback;
+ IKeystoreService mKeystoreService;
+
public KeyguardStateMonitor(Context context, IKeyguardService service, StateCallback callback) {
mLockPatternUtils = new LockPatternUtils(context);
mCurrentUserId = ActivityManager.getCurrentUser();
mCallback = callback;
+ mKeystoreService = IKeystoreService.Stub.asInterface(ServiceManager
+ .getService("android.security.keystore"));
+
try {
service.addStateMonitorCallback(this);
} catch (RemoteException e) {
@@ -86,6 +93,12 @@
@Override // Binder interface
public void onShowingStateChanged(boolean showing) {
mIsShowing = showing;
+
+ try {
+ mKeystoreService.onKeyguardVisibilityChanged(showing, mCurrentUserId);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error informing keystore of screen lock", e);
+ }
}
@Override // Binder interface
@@ -130,4 +143,4 @@
pw.println(prefix + "mTrusted=" + mTrusted);
pw.println(prefix + "mCurrentUserId=" + mCurrentUserId);
}
-}
\ No newline at end of file
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index 71c2ea1..1c9782f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -78,23 +78,6 @@
return false;
}
- @Override
- public boolean setPasswordBlacklist(ComponentName who, String name, List<String> blacklist,
- boolean parent) {
- return false;
- }
-
- @Override
- public String getPasswordBlacklistName(ComponentName who, @UserIdInt int userId,
- boolean parent) {
- return null;
- }
-
- @Override
- public boolean isPasswordBlacklisted(@UserIdInt int userId, String password) {
- return false;
- }
-
public boolean isUsingUnifiedPassword(ComponentName who) {
return true;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index ffa7311..90e8a9c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -820,7 +820,6 @@
private static final String TAG_PASSWORD_HISTORY_LENGTH = "password-history-length";
private static final String TAG_MIN_PASSWORD_LENGTH = "min-password-length";
private static final String ATTR_VALUE = "value";
- private static final String TAG_PASSWORD_BLACKLIST = "password-blacklist";
private static final String TAG_PASSWORD_QUALITY = "password-quality";
private static final String TAG_POLICIES = "policies";
private static final String TAG_CROSS_PROFILE_WIDGET_PROVIDERS =
@@ -961,9 +960,6 @@
// Default title of confirm credentials screen
String organizationName = null;
- // The blacklist data is stored in a file whose name is stored in the XML
- String passwordBlacklistFile = null;
-
// The component name of the backup transport which has to be used if backups are mandatory
// or null if backups are not mandatory.
ComponentName mandatoryBackupTransport = null;
@@ -1053,11 +1049,6 @@
out.endTag(null, TAG_MIN_PASSWORD_NONLETTER);
}
}
- if (passwordBlacklistFile != null) {
- out.startTag(null, TAG_PASSWORD_BLACKLIST);
- out.attribute(null, ATTR_VALUE, passwordBlacklistFile);
- out.endTag(null, TAG_PASSWORD_BLACKLIST);
- }
if (maximumTimeToUnlock != DEF_MAXIMUM_TIME_TO_UNLOCK) {
out.startTag(null, TAG_MAX_TIME_TO_UNLOCK);
out.attribute(null, ATTR_VALUE, Long.toString(maximumTimeToUnlock));
@@ -1313,8 +1304,6 @@
} else if (TAG_MIN_PASSWORD_NONLETTER.equals(tag)) {
minimumPasswordMetrics.nonLetter = Integer.parseInt(
parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_PASSWORD_BLACKLIST.equals(tag)) {
- passwordBlacklistFile = parser.getAttributeValue(null, ATTR_VALUE);
}else if (TAG_MAX_TIME_TO_UNLOCK.equals(tag)) {
maximumTimeToUnlock = Long.parseLong(
parser.getAttributeValue(null, ATTR_VALUE));
@@ -1589,8 +1578,6 @@
pw.println(minimumPasswordMetrics.symbols);
pw.print(prefix); pw.print("minimumPasswordNonLetter=");
pw.println(minimumPasswordMetrics.nonLetter);
- pw.print(prefix); pw.print("passwordBlacklist=");
- pw.println(passwordBlacklistFile != null);
pw.print(prefix); pw.print("maximumTimeToUnlock=");
pw.println(maximumTimeToUnlock);
pw.print(prefix); pw.print("strongAuthUnlockTimeout=");
@@ -1857,10 +1844,6 @@
return new LockPatternUtils(mContext);
}
- PasswordBlacklist newPasswordBlacklist(File file) {
- return new PasswordBlacklist(file);
- }
-
boolean storageManagerIsFileBasedEncryptionEnabled() {
return StorageManager.isFileEncryptedNativeOnly();
}
@@ -4413,136 +4396,6 @@
}
}
- /* @return the password blacklist set by the admin or {@code null} if none. */
- PasswordBlacklist getAdminPasswordBlacklistLocked(@NonNull ActiveAdmin admin) {
- final int userId = UserHandle.getUserId(admin.getUid());
- return admin.passwordBlacklistFile == null ? null : new PasswordBlacklist(
- new File(getPolicyFileDirectory(userId), admin.passwordBlacklistFile));
- }
-
- private static final String PASSWORD_BLACKLIST_FILE_PREFIX = "password-blacklist-";
- private static final String PASSWORD_BLACKLIST_FILE_SUFFIX = "";
-
- @Override
- public boolean setPasswordBlacklist(ComponentName who, String name, List<String> blacklist,
- boolean parent) {
- if (!mHasFeature) {
- return false;
- }
- Preconditions.checkNotNull(who, "who is null");
-
- synchronized (this) {
- final ActiveAdmin admin = getActiveAdminForCallerLocked(
- who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, parent);
- final int userId = mInjector.userHandleGetCallingUserId();
- PasswordBlacklist adminBlacklist = getAdminPasswordBlacklistLocked(admin);
-
- if (blacklist == null || blacklist.isEmpty()) {
- // Remove the adminBlacklist
- admin.passwordBlacklistFile = null;
- saveSettingsLocked(userId);
- if (adminBlacklist != null) {
- adminBlacklist.delete();
- }
- return true;
- }
-
- // Validate server side
- Preconditions.checkNotNull(name, "name is null");
- DevicePolicyManager.enforcePasswordBlacklistSize(blacklist);
-
- // Blacklist is case insensitive so normalize to lower case
- final int blacklistSize = blacklist.size();
- for (int i = 0; i < blacklistSize; ++i) {
- blacklist.set(i, blacklist.get(i).toLowerCase());
- }
-
- final boolean isNewBlacklist = adminBlacklist == null;
- if (isNewBlacklist) {
- // Create a new file for the blacklist. There could be multiple admins, each setting
- // different blacklists, to restrict a user's credential, for example a managed
- // profile can impose restrictions on its parent while the parent is already
- // restricted by its own admin. A deterministic naming scheme would be fragile if
- // new types of admin are introduced so we generate and save the file name instead.
- // This isn't a temporary file but it reuses the name generation logic
- final File file;
- try {
- file = File.createTempFile(PASSWORD_BLACKLIST_FILE_PREFIX,
- PASSWORD_BLACKLIST_FILE_SUFFIX, getPolicyFileDirectory(userId));
- } catch (IOException e) {
- Slog.e(LOG_TAG, "Failed to make a file for the blacklist", e);
- return false;
- }
- adminBlacklist = mInjector.newPasswordBlacklist(file);
- }
-
- if (adminBlacklist.savePasswordBlacklist(name, blacklist)) {
- if (isNewBlacklist) {
- // The blacklist was saved so point the admin to the file
- admin.passwordBlacklistFile = adminBlacklist.getFile().getName();
- saveSettingsLocked(userId);
- }
- return true;
- }
- }
-
- return false;
- }
-
- @Override
- public String getPasswordBlacklistName(ComponentName who, @UserIdInt int userId,
- boolean parent) {
- if (!mHasFeature) {
- return null;
- }
- Preconditions.checkNotNull(who, "who is null");
- enforceFullCrossUsersPermission(userId);
- synchronized (this) {
- final ActiveAdmin admin = getActiveAdminForCallerLocked(
- who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, parent);
- final PasswordBlacklist blacklist = getAdminPasswordBlacklistLocked(admin);
- if (blacklist == null) {
- return null;
- }
- return blacklist.getName();
- }
- }
-
- @Override
- public boolean isPasswordBlacklisted(@UserIdInt int userId, String password) {
- if (!mHasFeature) {
- return false;
- }
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.TEST_BLACKLISTED_PASSWORD, null);
- return isPasswordBlacklistedInternal(userId, password);
- }
-
- private boolean isPasswordBlacklistedInternal(@UserIdInt int userId, String password) {
- Preconditions.checkNotNull(password, "Password is null");
- enforceFullCrossUsersPermission(userId);
-
- // Normalize to lower case for case insensitive blacklist match
- final String lowerCasePassword = password.toLowerCase();
-
- synchronized (this) {
- final List<ActiveAdmin> admins =
- getActiveAdminsForLockscreenPoliciesLocked(userId, /* parent */ false);
- final int N = admins.size();
- for (int i = 0; i < N; i++) {
- final PasswordBlacklist blacklist
- = getAdminPasswordBlacklistLocked(admins.get(i));
- if (blacklist != null) {
- if (blacklist.isPasswordBlacklisted(lowerCasePassword)) {
- return true;
- }
- }
- }
- }
-
- return false;
- }
-
@Override
public boolean isActivePasswordSufficient(int userHandle, boolean parent) {
if (!mHasFeature) {
@@ -4938,11 +4791,6 @@
return false;
}
}
-
- if (isPasswordBlacklistedInternal(userHandle, password)) {
- Slog.w(LOG_TAG, "resetPassword: the password is blacklisted");
- return false;
- }
}
DevicePolicyData policy = getUserData(userHandle);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PasswordBlacklist.java b/services/devicepolicy/java/com/android/server/devicepolicy/PasswordBlacklist.java
deleted file mode 100644
index a17a107..0000000
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PasswordBlacklist.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.devicepolicy;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.util.AtomicFile;
-import android.util.Slog;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.List;
-
-/**
- * Manages the blacklisted passwords.
- *
- * This caller must ensure synchronized access.
- */
-public class PasswordBlacklist {
- private static final String TAG = "PasswordBlacklist";
-
- private final AtomicFile mFile;
-
- /**
- * Create an object to manage the password blacklist.
- *
- * This is a lightweight operation to prepare variables but not perform any IO.
- */
- public PasswordBlacklist(File file) {
- mFile = new AtomicFile(file, "device-policy");
- }
-
- /**
- * Atomically replace the blacklist.
- *
- * Pass {@code null} for an empty list.
- */
- public boolean savePasswordBlacklist(@NonNull String name, @NonNull List<String> blacklist) {
- FileOutputStream fos = null;
- try {
- fos = mFile.startWrite();
- final DataOutputStream out = buildStreamForWriting(fos);
- final Header header = new Header(Header.VERSION_1, name, blacklist.size());
- header.write(out);
- final int blacklistSize = blacklist.size();
- for (int i = 0; i < blacklistSize; ++i) {
- out.writeUTF(blacklist.get(i));
- }
- out.flush();
- mFile.finishWrite(fos);
- return true;
- } catch (IOException e) {
- mFile.failWrite(fos);
- return false;
- }
- }
-
- /** @return the name of the blacklist or {@code null} if none set. */
- public String getName() {
- try (DataInputStream in = openForReading()) {
- return Header.read(in).mName;
- } catch (IOException e) {
- Slog.wtf(TAG, "Failed to read blacklist file", e);
- }
- return null;
- }
-
- /** @return the number of blacklisted passwords. */
- public int getSize() {
- final int blacklistSize;
- try (DataInputStream in = openForReading()) {
- return Header.read(in).mSize;
- } catch (IOException e) {
- Slog.wtf(TAG, "Failed to read blacklist file", e);
- }
- return 0;
- }
-
- /** @return whether the password matches an blacklisted item. */
- public boolean isPasswordBlacklisted(@NonNull String password) {
- final int blacklistSize;
- try (DataInputStream in = openForReading()) {
- final Header header = Header.read(in);
- for (int i = 0; i < header.mSize; ++i) {
- if (in.readUTF().equals(password)) {
- return true;
- }
- }
- } catch (IOException e) {
- Slog.wtf(TAG, "Failed to read blacklist file", e);
- // Fail safe and block all passwords. Setting a new blacklist should resolve this
- // problem which can be identified by examining the log.
- return true;
- }
- return false;
- }
-
- /** Delete the blacklist completely from disk. */
- public void delete() {
- mFile.delete();
- }
-
- /** Get the file the blacklist is stored in. */
- public File getFile() {
- return mFile.getBaseFile();
- }
-
- private DataOutputStream buildStreamForWriting(FileOutputStream fos) {
- return new DataOutputStream(new BufferedOutputStream(fos));
- }
-
- private DataInputStream openForReading() throws IOException {
- return new DataInputStream(new BufferedInputStream(mFile.openRead()));
- }
-
- /**
- * Helper to read and write the header of the blacklist file.
- */
- private static class Header {
- static final int VERSION_1 = 1;
-
- final int mVersion; // File format version
- final String mName;
- final int mSize;
-
- Header(int version, String name, int size) {
- mVersion = version;
- mName = name;
- mSize = size;
- }
-
- void write(DataOutputStream out) throws IOException {
- out.writeInt(mVersion);
- out.writeUTF(mName);
- out.writeInt(mSize);
- }
-
- static Header read(DataInputStream in) throws IOException {
- final int version = in.readInt();
- final String name = in.readUTF();
- final int size = in.readInt();
- return new Header(version, name, size);
- }
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index 520f318..cd39285 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -98,12 +98,6 @@
this.context = injector.context;
}
- @Override
- public boolean isPasswordBlacklisted(int userId, String password) {
- return false;
- }
-
-
public void notifyChangeToContentObserver(Uri uri, int userHandle) {
ContentObserver co = mMockInjector.mContentObservers.get(new Pair<>(uri, userHandle));
if (co != null) {
@@ -220,11 +214,6 @@
}
@Override
- PasswordBlacklist newPasswordBlacklist(File file) {
- return services.passwordBlacklist;
- }
-
- @Override
boolean storageManagerIsFileBasedEncryptionEnabled() {
return services.storageManager.isFileBasedEncryptionEnabled();
}
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 ccf4a82..b76064b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -4192,36 +4192,6 @@
assertTrue(dpm.clearResetPasswordToken(admin1));
}
- public void testSetPasswordBlacklistCannotBeCalledByNonAdmin() throws Exception {
- assertExpectException(SecurityException.class, /* messageRegex= */ null,
- () -> dpm.setPasswordBlacklist(admin1, null, null));
- verifyZeroInteractions(getServices().passwordBlacklist);
- }
-
- public void testClearingPasswordBlacklistDoesNotCreateNewBlacklist() throws Exception {
- setupProfileOwner();
- dpm.setPasswordBlacklist(admin1, null, null);
- verifyZeroInteractions(getServices().passwordBlacklist);
- }
-
- public void testSetPasswordBlacklistCreatesNewBlacklist() throws Exception {
- final String name = "myblacklist";
- final List<String> explicit = Arrays.asList("password", "letmein");
- setupProfileOwner();
- dpm.setPasswordBlacklist(admin1, name, explicit);
- verify(getServices().passwordBlacklist).savePasswordBlacklist(name, explicit);
- }
-
- public void testSetPasswordBlacklistOnlyConvertsExplicitToLowerCase() throws Exception {
- final List<String> mixedCase = Arrays.asList("password", "LETMEIN", "FooTBAll");
- final List<String> lowerCase = Arrays.asList("password", "letmein", "football");
- mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
- setupDeviceOwner();
- final String name = "Name of the Blacklist";
- dpm.setPasswordBlacklist(admin1, name, mixedCase);
- verify(getServices().passwordBlacklist).savePasswordBlacklist(name, lowerCase);
- }
-
public void testIsActivePasswordSufficient() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
mContext.packageName = admin1.getPackageName();
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 81ed6e2..e753df1 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -96,7 +96,6 @@
public final IBackupManager ibackupManager;
public final IAudioService iaudioService;
public final LockPatternUtils lockPatternUtils;
- public final PasswordBlacklist passwordBlacklist;
public final StorageManagerForMock storageManager;
public final WifiManager wifiManager;
public final SettingsForMock settings;
@@ -135,7 +134,6 @@
ibackupManager = mock(IBackupManager.class);
iaudioService = mock(IAudioService.class);
lockPatternUtils = mock(LockPatternUtils.class);
- passwordBlacklist = mock(PasswordBlacklist.class);
storageManager = mock(StorageManagerForMock.class);
wifiManager = mock(WifiManager.class);
settings = mock(SettingsForMock.class);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/PasswordBlacklistTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/PasswordBlacklistTest.java
deleted file mode 100644
index 1b3fc2c..0000000
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/PasswordBlacklistTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.devicepolicy;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Unit tests for {@link PasswordBlacklist}.
- *
- * bit FrameworksServicesTests:com.android.server.devicepolicy.PasswordBlacklistTest
- * runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/devicepolicy/PasswordBlacklistTest.java
- */
-@RunWith(AndroidJUnit4.class)
-public final class PasswordBlacklistTest {
- private File mBlacklistFile;
- private PasswordBlacklist mBlacklist;
-
- @Before
- public void setUp() throws IOException {
- mBlacklistFile = File.createTempFile("pwdbl", null);
- mBlacklist = new PasswordBlacklist(mBlacklistFile);
- }
-
- @After
- public void tearDown() {
- mBlacklist.delete();
- }
-
- @Test
- public void matchIsExact() {
- // Note: Case sensitivity is handled by the user of PasswordBlacklist by normalizing the
- // values stored in and tested against it.
- mBlacklist.savePasswordBlacklist("matchIsExact", Arrays.asList("password", "qWERty"));
- assertTrue(mBlacklist.isPasswordBlacklisted("password"));
- assertTrue(mBlacklist.isPasswordBlacklisted("qWERty"));
- assertFalse(mBlacklist.isPasswordBlacklisted("Password"));
- assertFalse(mBlacklist.isPasswordBlacklisted("qwert"));
- assertFalse(mBlacklist.isPasswordBlacklisted("letmein"));
- }
-
- @Test
- public void matchIsNotRegex() {
- mBlacklist.savePasswordBlacklist("matchIsNotRegex", Arrays.asList("a+b*"));
- assertTrue(mBlacklist.isPasswordBlacklisted("a+b*"));
- assertFalse(mBlacklist.isPasswordBlacklisted("aaaa"));
- assertFalse(mBlacklist.isPasswordBlacklisted("abbbb"));
- assertFalse(mBlacklist.isPasswordBlacklisted("aaaa"));
- }
-
- @Test
- public void matchFailsSafe() throws IOException {
- try (FileOutputStream fos = new FileOutputStream(mBlacklistFile)) {
- // Write a malformed blacklist file
- fos.write(17);
- }
- assertTrue(mBlacklist.isPasswordBlacklisted("anything"));
- assertTrue(mBlacklist.isPasswordBlacklisted("at"));
- assertTrue(mBlacklist.isPasswordBlacklisted("ALL"));
- }
-
- @Test
- public void blacklistCanBeNamed() {
- final String name = "identifier";
- mBlacklist.savePasswordBlacklist(name, Arrays.asList("one", "two", "three"));
- assertEquals(mBlacklist.getName(), name);
- }
-
- @Test
- public void reportsTheCorrectNumberOfEntries() {
- mBlacklist.savePasswordBlacklist("Count Entries", Arrays.asList("1", "2", "3", "4"));
- assertEquals(mBlacklist.getSize(), 4);
- }
-
- @Test
- public void reportsBlacklistFile() {
- assertEquals(mBlacklistFile, mBlacklist.getFile());
- }
-}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java
index 36136a8..ce74457 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ScheduleCalendarTest.java
@@ -206,6 +206,31 @@
}
@Test
+ public void testShouldExitForAlarm_oldAlarm() {
+ // Cal: today 2:15pm
+ Calendar cal = new GregorianCalendar();
+ cal.set(Calendar.HOUR_OF_DAY, 14);
+ cal.set(Calendar.MINUTE, 15);
+ cal.set(Calendar.SECOND, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+
+ // ScheduleInfo: today 12:16pm - today 3:15pm
+ mScheduleInfo.days = new int[] {getTodayDay()};
+ mScheduleInfo.startHour = 12;
+ mScheduleInfo.endHour = 3;
+ mScheduleInfo.startMinute = 16;
+ mScheduleInfo.endMinute = 15;
+ mScheduleInfo.exitAtAlarm = true;
+ mScheduleInfo.nextAlarm = 1000; // very old alarm
+
+ mScheduleCalendar.setSchedule(mScheduleInfo);
+ assertTrue(mScheduleCalendar.isInSchedule(cal.getTimeInMillis()));
+
+ // don't exit for an alarm if it's an old alarm
+ assertFalse(mScheduleCalendar.shouldExitForAlarm(1000));
+ }
+
+ @Test
public void testMaybeSetNextAlarm_settingOff() {
mScheduleInfo.exitAtAlarm = false;
mScheduleInfo.nextAlarm = 0;