summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/ContentResolver.java1
-rw-r--r--core/java/android/content/pm/RegisteredServicesCache.java59
-rw-r--r--core/java/android/view/ViewRootImpl.java21
-rw-r--r--core/res/res/values/config.xml90
-rw-r--r--core/res/res/values/symbols.xml9
-rw-r--r--core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java41
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/Utils.java7
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeService.java7
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java9
-rw-r--r--services/core/java/com/android/server/display/AutomaticBrightnessController.java82
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java47
-rw-r--r--services/core/java/com/android/server/display/HysteresisLevels.java74
-rw-r--r--services/core/java/com/android/server/locksettings/SP800Derive.java82
-rw-r--r--services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java56
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java22
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/SP800DeriveTests.java40
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java14
-rw-r--r--telephony/java/android/telephony/SmsManager.java11
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java21
20 files changed, 520 insertions, 177 deletions
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index c109ed2dcfe3..a061e610fd40 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -77,6 +77,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* <p>For more information about using a ContentResolver with content providers, read the
* <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
* developer guide.</p>
+ * </div>
*/
public abstract class ContentResolver {
/**
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 020e8c22b128..c8f046775211 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -17,6 +17,7 @@
package android.content.pm;
import android.Manifest;
+import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -174,7 +175,8 @@ public abstract class RegisteredServicesCache<V> {
mContext.registerReceiver(mUserRemovedReceiver, userFilter);
}
- private final void handlePackageEvent(Intent intent, int userId) {
+ @VisibleForTesting
+ protected void handlePackageEvent(Intent intent, int userId) {
// Don't regenerate the services map when the package is removed or its
// ASEC container unmounted as a step in replacement. The subsequent
// _ADDED / _AVAILABLE call will regenerate the map in the final state.
@@ -236,6 +238,9 @@ public abstract class RegisteredServicesCache<V> {
public void invalidateCache(int userId) {
synchronized (mServicesLock) {
+ if (DEBUG) {
+ Slog.d(TAG, "invalidating cache for " + userId + " " + mInterfaceName);
+ }
final UserServices<V> user = findOrCreateUserLocked(userId);
user.services = null;
onServicesChangedLocked(userId);
@@ -460,34 +465,48 @@ public abstract class RegisteredServicesCache<V> {
* or null to assume that everything is affected.
* @param userId the user for whom to update the services map.
*/
- private void generateServicesMap(int[] changedUids, int userId) {
+ private void generateServicesMap(@Nullable int[] changedUids, int userId) {
if (DEBUG) {
Slog.d(TAG, "generateServicesMap() for " + userId + ", changed UIDs = "
+ Arrays.toString(changedUids));
}
- final ArrayList<ServiceInfo<V>> serviceInfos = new ArrayList<>();
- final List<ResolveInfo> resolveInfos = queryIntentServices(userId);
- for (ResolveInfo resolveInfo : resolveInfos) {
- try {
- ServiceInfo<V> info = parseServiceInfo(resolveInfo);
- if (info == null) {
- Log.w(TAG, "Unable to load service info " + resolveInfo.toString());
- continue;
- }
- serviceInfos.add(info);
- } catch (XmlPullParserException|IOException e) {
- Log.w(TAG, "Unable to load service info " + resolveInfo.toString(), e);
- }
- }
-
synchronized (mServicesLock) {
final UserServices<V> user = findOrCreateUserLocked(userId);
- final boolean firstScan = user.services == null;
- if (firstScan) {
+ final boolean cacheInvalid = user.services == null;
+ if (cacheInvalid) {
user.services = Maps.newHashMap();
}
+ final ArrayList<ServiceInfo<V>> serviceInfos = new ArrayList<>();
+ final List<ResolveInfo> resolveInfos = queryIntentServices(userId);
+
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ try {
+ // when changedUids == null, we want to do a rescan of everything, this means
+ // it's the initial scan, and containsUid will trivially return true
+ // when changedUids != null, we got here because a package changed, but
+ // invalidateCache could have been called (thus user.services == null), and we
+ // should query from PackageManager again
+ if (!cacheInvalid
+ && !containsUid(
+ changedUids, resolveInfo.serviceInfo.applicationInfo.uid)) {
+ if (DEBUG) {
+ Slog.d(TAG, "Skipping parseServiceInfo for " + resolveInfo);
+ }
+ continue;
+ }
+ ServiceInfo<V> info = parseServiceInfo(resolveInfo);
+ if (info == null) {
+ Log.w(TAG, "Unable to load service info " + resolveInfo.toString());
+ continue;
+ }
+ serviceInfos.add(info);
+ } catch (XmlPullParserException | IOException e) {
+ Log.w(TAG, "Unable to load service info " + resolveInfo.toString(), e);
+ }
+ }
+
StringBuilder changes = new StringBuilder();
boolean changed = false;
for (ServiceInfo<V> info : serviceInfos) {
@@ -508,7 +527,7 @@ public abstract class RegisteredServicesCache<V> {
changed = true;
user.services.put(info.type, info);
user.persistentServices.put(info.type, info.uid);
- if (!(user.mPersistentServicesFileDidNotExist && firstScan)) {
+ if (!(user.mPersistentServicesFileDidNotExist && cacheInvalid)) {
notifyListener(info.type, userId, false /* removed */);
}
} else if (previousUid == info.uid) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6df0173d9684..a1c0967f0ab1 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1354,6 +1354,9 @@ public final class ViewRootImpl implements ViewParent,
}
if (mStopped) {
+ if (mSurfaceHolder != null) {
+ notifySurfaceDestroyed();
+ }
mSurface.release();
}
}
@@ -2227,13 +2230,7 @@ public final class ViewRootImpl implements ViewParent,
}
mIsCreating = false;
} else if (hadSurface) {
- mSurfaceHolder.ungetCallbacks();
- SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
- if (callbacks != null) {
- for (SurfaceHolder.Callback c : callbacks) {
- c.surfaceDestroyed(mSurfaceHolder);
- }
- }
+ notifySurfaceDestroyed();
mSurfaceHolder.mSurfaceLock.lock();
try {
mSurfaceHolder.mSurface = new Surface();
@@ -2497,6 +2494,16 @@ public final class ViewRootImpl implements ViewParent,
mIsInTraversal = false;
}
+ private void notifySurfaceDestroyed() {
+ mSurfaceHolder.ungetCallbacks();
+ SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks();
+ if (callbacks != null) {
+ for (SurfaceHolder.Callback c : callbacks) {
+ c.surfaceDestroyed(mSurfaceHolder);
+ }
+ }
+ }
+
private void maybeHandleWindowMove(Rect frame) {
// TODO: Well, we are checking whether the frame has changed similarly
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8af8f8ba0fee..7eedb64b1c50 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1436,26 +1436,6 @@
<integer-array name="config_autoBrightnessKeyboardBacklightValues">
</integer-array>
- <!-- Array of hysteresis constraint values for brightening, represented as tenths of a
- percent. The length of this array is assumed to be one greater than
- config_dynamicHysteresisLuxLevels. The brightening threshold is calculated as
- lux * (1.0f + CONSTRAINT_VALUE). When the current lux is higher than this threshold,
- the screen brightness is recalculated. See the config_dynamicHysteresisLuxLevels
- description for how the constraint value is chosen. -->
- <integer-array name="config_dynamicHysteresisBrightLevels">
- <item>100</item>
- </integer-array>
-
- <!-- Array of hysteresis constraint values for darkening, represented as tenths of a
- percent. The length of this array is assumed to be one greater than
- config_dynamicHysteresisLuxLevels. The darkening threshold is calculated as
- lux * (1.0f - CONSTRAINT_VALUE). When the current lux is lower than this threshold,
- the screen brightness is recalculated. See the config_dynamicHysteresisLuxLevels
- description for how the constraint value is chosen. -->
- <integer-array name="config_dynamicHysteresisDarkLevels">
- <item>200</item>
- </integer-array>
-
<!-- An array describing the screen's backlight values corresponding to the brightness
values in the config_screenBrightnessNits array.
@@ -1473,19 +1453,73 @@
<array name="config_screenBrightnessNits">
</array>
-
<!-- Array of ambient lux threshold values. This is used for determining hysteresis constraint
values by calculating the index to use for lookup and then setting the constraint value
to the corresponding value of the array. The new brightening hysteresis constraint value
- is the n-th element of config_dynamicHysteresisBrightLevels, and the new darkening
- hysteresis constraint value is the n-th element of config_dynamicHysteresisDarkLevels.
+ is the n-th element of config_ambientBrighteningThresholds, and the new darkening
+ hysteresis constraint value is the n-th element of config_ambientDarkeningThresholds.
The (zero-based) index is calculated as follows: (MAX is the largest index of the array)
- condition calculated index
- value < lux[0] 0
- lux[n] <= value < lux[n+1] n+1
- lux[MAX] <= value MAX+1 -->
- <integer-array name="config_dynamicHysteresisLuxLevels">
+ condition calculated index
+ value < level[0] 0
+ level[n] <= value < level[n+1] n+1
+ level[MAX] <= value MAX+1 -->
+ <integer-array name="config_ambientThresholdLevels">
+ </integer-array>
+
+ <!-- Array of hysteresis constraint values for brightening, represented as tenths of a
+ percent. The length of this array is assumed to be one greater than
+ config_ambientThresholdLevels. The brightening threshold is calculated as
+ lux * (1.0f + CONSTRAINT_VALUE). When the current lux is higher than this threshold,
+ the screen brightness is recalculated. See the config_ambientThresholdLevels
+ description for how the constraint value is chosen. -->
+ <integer-array name="config_ambientBrighteningThresholds">
+ <item>100</item>
+ </integer-array>
+
+ <!-- Array of hysteresis constraint values for darkening, represented as tenths of a
+ percent. The length of this array is assumed to be one greater than
+ config_ambientThresholdLevels. The darkening threshold is calculated as
+ lux * (1.0f - CONSTRAINT_VALUE). When the current lux is lower than this threshold,
+ the screen brightness is recalculated. See the config_ambientThresholdLevels
+ description for how the constraint value is chosen. -->
+ <integer-array name="config_ambientDarkeningThresholds">
+ <item>200</item>
+ </integer-array>
+
+ <!-- Array of screen brightness threshold values. This is used for determining hysteresis
+ constraint values by calculating the index to use for lookup and then setting the
+ constraint value to the corresponding value of the array. The new brightening hysteresis
+ constraint value is the n-th element of config_screenBrighteningThresholds, and the new
+ darkening hysteresis constraint value is the n-th element of
+ config_screenDarkeningThresholds.
+
+ The (zero-based) index is calculated as follows: (MAX is the largest index of the array)
+ condition calculated index
+ value < level[0] 0
+ level[n] <= value < level[n+1] n+1
+ level[MAX] <= value MAX+1 -->
+ <integer-array name="config_screenThresholdLevels">
+ </integer-array>
+
+ <!-- Array of hysteresis constraint values for brightening, represented as tenths of a
+ percent. The length of this array is assumed to be one greater than
+ config_screenThresholdLevels. The brightening threshold is calculated as
+ screenBrightness * (1.0f + CONSTRAINT_VALUE). When the new screen brightness is higher
+ than this threshold, it is applied. See the config_screenThresholdLevels description for
+ how the constraint value is chosen. -->
+ <integer-array name="config_screenBrighteningThresholds">
+ <item>100</item>
+ </integer-array>
+
+ <!-- Array of hysteresis constraint values for darkening, represented as tenths of a
+ percent. The length of this array is assumed to be one greater than
+ config_screenThresholdLevels. The darkening threshold is calculated as
+ screenBrightness * (1.0f - CONSTRAINT_VALUE). When the new screen brightness is lower than
+ this threshold, it is applied. See the config_screenThresholdLevels description for how
+ the constraint value is chosen. -->
+ <integer-array name="config_screenDarkeningThresholds">
+ <item>200</item>
</integer-array>
<!-- Amount of time it takes for the light sensor to warm up in milliseconds.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d893468a53f8..b6ea05b7d5aa 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1823,9 +1823,12 @@
<java-symbol type="array" name="config_autoBrightnessKeyboardBacklightValues" />
<java-symbol type="array" name="config_autoBrightnessLcdBacklightValues" />
<java-symbol type="array" name="config_autoBrightnessLevels" />
- <java-symbol type="array" name="config_dynamicHysteresisBrightLevels" />
- <java-symbol type="array" name="config_dynamicHysteresisDarkLevels" />
- <java-symbol type="array" name="config_dynamicHysteresisLuxLevels" />
+ <java-symbol type="array" name="config_ambientThresholdLevels" />
+ <java-symbol type="array" name="config_ambientBrighteningThresholds" />
+ <java-symbol type="array" name="config_ambientDarkeningThresholds" />
+ <java-symbol type="array" name="config_screenThresholdLevels" />
+ <java-symbol type="array" name="config_screenBrighteningThresholds" />
+ <java-symbol type="array" name="config_screenDarkeningThresholds" />
<java-symbol type="array" name="config_minimumBrightnessCurveLux" />
<java-symbol type="array" name="config_minimumBrightnessCurveNits" />
<java-symbol type="array" name="config_protectedNetworks" />
diff --git a/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java b/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
index d3d1f22af3cb..c8b449e68da7 100644
--- a/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
+++ b/core/tests/coretests/src/android/content/pm/RegisteredServicesCacheTest.java
@@ -16,6 +16,7 @@
package android.content.pm;
+import android.content.Intent;
import android.content.res.Resources;
import android.os.FileUtils;
import android.os.Parcel;
@@ -188,6 +189,36 @@ public class RegisteredServicesCacheTest extends AndroidTestCase {
assertEquals(0, cache.getPersistentServicesSize(u1));
}
+ /**
+ * Check that an optimization to skip a call to PackageManager handles an invalidated cache.
+ *
+ * We added an optimization in generateServicesMap to only query PackageManager for packages
+ * that have been changed, because if a package is unchanged, we have already cached the
+ * services info for it, so we can save a query to PackageManager (and save some memory).
+ * However, if invalidateCache was called, we cannot optimize, and must do a full query.
+ * The initial optimization was buggy because it failed to check for an invalidated cache, and
+ * only scanned the changed packages, given in the ACTION_PACKAGE_CHANGED intent (b/122912184).
+ */
+ public void testParseServiceInfoOptimizationHandlesInvalidatedCache() {
+ TestServicesCache cache = new TestServicesCache();
+ cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1));
+ cache.addServiceForQuerying(U0, r2, newServiceInfo(t2, UID2));
+ assertEquals(2, cache.getAllServicesSize(U0));
+
+ // simulate the client of the cache invalidating it
+ cache.invalidateCache(U0);
+
+ // there should be 0 services (userServices.services == null ) at this point, but we don't
+ // call getAllServicesSize since that would force a full scan of packages,
+ // instead we trigger a package change in a package that is in the list of services
+ Intent intent = new Intent(Intent.ACTION_PACKAGE_CHANGED);
+ intent.putExtra(Intent.EXTRA_UID, UID1);
+ cache.handlePackageEvent(intent, U0);
+
+ // check that the optimization does a full query and caches both services
+ assertEquals(2, cache.getAllServicesSize(U0));
+ }
+
private static RegisteredServicesCache.ServiceInfo<TestServiceType> newServiceInfo(
TestServiceType type, int uid) {
final ComponentInfo info = new ComponentInfo();
@@ -265,6 +296,11 @@ public class RegisteredServicesCacheTest extends AndroidTestCase {
map = new HashMap<>();
mServices.put(userId, map);
}
+ // in actual cases, resolveInfo should always have a serviceInfo, since we specifically
+ // query for intent services
+ resolveInfo.serviceInfo = new android.content.pm.ServiceInfo();
+ resolveInfo.serviceInfo.applicationInfo =
+ new ApplicationInfo(serviceInfo.componentInfo.applicationInfo);
map.put(resolveInfo, serviceInfo);
}
@@ -303,6 +339,11 @@ public class RegisteredServicesCacheTest extends AndroidTestCase {
public void onUserRemoved(int userId) {
super.onUserRemoved(userId);
}
+
+ @Override
+ public void handlePackageEvent(Intent intent, int userId) {
+ super.handlePackageEvent(intent, userId);
+ }
}
static class TestSerializer implements XmlSerializerAndParser<TestServiceType> {
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 505cfeac220c..2d321f9a1a9a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -35,8 +35,8 @@ public class Utils {
private static final String CURRENT_MODE_KEY = "CURRENT_MODE";
private static final String NEW_MODE_KEY = "NEW_MODE";
@VisibleForTesting
- static final String STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY =
- "ro.storage_manager.show_opt_in";
+ static final String STORAGE_MANAGER_ENABLED_PROPERTY =
+ "ro.storage_manager.enabled";
private static Signature[] sSystemSignature;
private static String sPermissionControllerPackageName;
@@ -353,8 +353,7 @@ public class Utils {
public static boolean isStorageManagerEnabled(Context context) {
boolean isDefaultOn;
try {
- // Turn off by default if the opt-in was shown.
- isDefaultOn = !SystemProperties.getBoolean(STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY, true);
+ isDefaultOn = SystemProperties.getBoolean(STORAGE_MANAGER_ENABLED_PROPERTY, false);
} catch (Resources.NotFoundException e) {
isDefaultOn = false;
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
index a79f841e70c6..2dd57ff60bbe 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
@@ -17,7 +17,7 @@ package com.android.settingslib;
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
-import static com.android.settingslib.Utils.STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY;
+import static com.android.settingslib.Utils.STORAGE_MANAGER_ENABLED_PROPERTY;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.argThat;
@@ -160,7 +160,7 @@ public class UtilsTest {
@Test
public void testIsStorageManagerEnabled_UsesSystemProperties() {
- SystemProperties.set(STORAGE_MANAGER_SHOW_OPT_IN_PROPERTY, "false");
+ SystemProperties.set(STORAGE_MANAGER_ENABLED_PROPERTY, "true");
assertThat(Utils.isStorageManagerEnabled(mContext)).isTrue();
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 73393047cc45..f495cedbf028 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -38,6 +38,7 @@ public class DozeService extends DreamService
private DozeMachine mDozeMachine;
private DozeServicePlugin mDozePlugin;
+ private PluginManager mPluginManager;
public DozeService() {
setDebug(DEBUG);
@@ -53,14 +54,14 @@ public class DozeService extends DreamService
finish();
return;
}
- Dependency.get(PluginManager.class).addPluginListener(this,
- DozeServicePlugin.class, false /* Allow multiple */);
+ mPluginManager = Dependency.get(PluginManager.class);
+ mPluginManager.addPluginListener(this, DozeServicePlugin.class, false /* allowMultiple */);
mDozeMachine = new DozeFactory().assembleMachine(this);
}
@Override
public void onDestroy() {
- Dependency.get(PluginManager.class).removePluginListener(this);
+ mPluginManager.removePluginListener(this);
super.onDestroy();
mDozeMachine = null;
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index f79a51b13afd..47b646c1a667 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -48,6 +48,7 @@ import android.content.pm.PermissionInfo;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
@@ -1288,9 +1289,13 @@ class AlarmManagerService extends SystemService {
// because kernel doesn't keep this after reboot
setTimeZoneImpl(SystemProperties.get(TIMEZONE_PROPERTY));
- // Also sure that we're booting with a halfway sensible current time
if (mNativeData != 0) {
- final long systemBuildTime = Environment.getRootDirectory().lastModified();
+ // Ensure that we're booting with a halfway sensible current time. Use the
+ // most recent of Build.TIME, the root file system's timestamp, and the
+ // value of the ro.build.date.utc system property (which is in seconds).
+ final long systemBuildTime = Long.max(
+ 1000L * SystemProperties.getLong("ro.build.date.utc", -1L),
+ Long.max(Environment.getRootDirectory().lastModified(), Build.TIME));
if (System.currentTimeMillis() < systemBuildTime) {
Slog.i(TAG, "Current time only " + System.currentTimeMillis()
+ ", advancing to build time " + systemBuildTime);
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 1c3342a9af42..2612b53e1052 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -16,30 +16,26 @@
package com.android.server.display;
-import com.android.server.EventLogTags;
-import com.android.server.LocalServices;
-
import android.annotation.Nullable;
-import android.app.ActivityManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.display.BrightnessConfiguration;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
-import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.Trace;
-import android.text.format.DateUtils;
import android.util.EventLog;
import android.util.MathUtils;
import android.util.Slog;
import android.util.TimeUtils;
+import com.android.server.EventLogTags;
+
import java.io.PrintWriter;
class AutomaticBrightnessController {
@@ -127,7 +123,8 @@ class AutomaticBrightnessController {
private final int mWeightingIntercept;
// Configuration object for determining thresholds to change brightness dynamically
- private final HysteresisLevels mHysteresisLevels;
+ private final HysteresisLevels mAmbientBrightnessThresholds;
+ private final HysteresisLevels mScreenBrightnessThresholds;
// Amount of time to delay auto-brightness after screen on while waiting for
// the light sensor to warm-up in milliseconds.
@@ -147,8 +144,12 @@ class AutomaticBrightnessController {
private boolean mAmbientLuxValid;
// The ambient light level threshold at which to brighten or darken the screen.
- private float mBrighteningLuxThreshold;
- private float mDarkeningLuxThreshold;
+ private float mAmbientBrighteningThreshold;
+ private float mAmbientDarkeningThreshold;
+
+ // The screen light level threshold at which to brighten or darken the screen.
+ private float mScreenBrighteningThreshold;
+ private float mScreenDarkeningThreshold;
// The most recent light sample.
private float mLastObservedLux;
@@ -196,7 +197,8 @@ class AutomaticBrightnessController {
int lightSensorWarmUpTime, int brightnessMin, int brightnessMax, float dozeScaleFactor,
int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig,
long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
- HysteresisLevels hysteresisLevels) {
+ HysteresisLevels ambientBrightnessThresholds,
+ HysteresisLevels screenBrightnessThresholds) {
mCallbacks = callbacks;
mSensorManager = sensorManager;
mBrightnessMapper = mapper;
@@ -212,7 +214,8 @@ class AutomaticBrightnessController {
mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig;
mAmbientLightHorizon = AMBIENT_LIGHT_LONG_HORIZON_MILLIS;
mWeightingIntercept = AMBIENT_LIGHT_LONG_HORIZON_MILLIS;
- mHysteresisLevels = hysteresisLevels;
+ mAmbientBrightnessThresholds = ambientBrightnessThresholds;
+ mScreenBrightnessThresholds = screenBrightnessThresholds;
mShortTermModelValid = true;
mShortTermModelAnchor = -1;
@@ -364,8 +367,10 @@ class AutomaticBrightnessController {
pw.println(" mCurrentLightSensorRate=" + mCurrentLightSensorRate);
pw.println(" mAmbientLux=" + mAmbientLux);
pw.println(" mAmbientLuxValid=" + mAmbientLuxValid);
- pw.println(" mBrighteningLuxThreshold=" + mBrighteningLuxThreshold);
- pw.println(" mDarkeningLuxThreshold=" + mDarkeningLuxThreshold);
+ pw.println(" mAmbientBrighteningThreshold=" + mAmbientBrighteningThreshold);
+ pw.println(" mAmbientDarkeningThreshold=" + mAmbientDarkeningThreshold);
+ pw.println(" mScreenBrighteningThreshold=" + mScreenBrighteningThreshold);
+ pw.println(" mScreenDarkeningThreshold=" + mScreenDarkeningThreshold);
pw.println(" mLastObservedLux=" + mLastObservedLux);
pw.println(" mLastObservedLuxTime=" + TimeUtils.formatUptime(mLastObservedLuxTime));
pw.println(" mRecentLightSamples=" + mRecentLightSamples);
@@ -384,7 +389,8 @@ class AutomaticBrightnessController {
mBrightnessMapper.dump(pw);
pw.println();
- mHysteresisLevels.dump(pw);
+ mAmbientBrightnessThresholds.dump(pw);
+ mScreenBrightnessThresholds.dump(pw);
}
private boolean setLightSensorEnabled(boolean enable) {
@@ -459,8 +465,8 @@ class AutomaticBrightnessController {
lux = 0;
}
mAmbientLux = lux;
- mBrighteningLuxThreshold = mHysteresisLevels.getBrighteningThreshold(lux);
- mDarkeningLuxThreshold = mHysteresisLevels.getDarkeningThreshold(lux);
+ mAmbientBrighteningThreshold = mAmbientBrightnessThresholds.getBrighteningThreshold(lux);
+ mAmbientDarkeningThreshold = mAmbientBrightnessThresholds.getDarkeningThreshold(lux);
// If the short term model was invalidated and the change is drastic enough, reset it.
if (!mShortTermModelValid && mShortTermModelAnchor != -1) {
@@ -551,7 +557,7 @@ class AutomaticBrightnessController {
final int N = mAmbientLightRingBuffer.size();
long earliestValidTime = time;
for (int i = N - 1; i >= 0; i--) {
- if (mAmbientLightRingBuffer.getLux(i) <= mBrighteningLuxThreshold) {
+ if (mAmbientLightRingBuffer.getLux(i) <= mAmbientBrighteningThreshold) {
break;
}
earliestValidTime = mAmbientLightRingBuffer.getTime(i);
@@ -563,7 +569,7 @@ class AutomaticBrightnessController {
final int N = mAmbientLightRingBuffer.size();
long earliestValidTime = time;
for (int i = N - 1; i >= 0; i--) {
- if (mAmbientLightRingBuffer.getLux(i) >= mDarkeningLuxThreshold) {
+ if (mAmbientLightRingBuffer.getLux(i) >= mAmbientDarkeningThreshold) {
break;
}
earliestValidTime = mAmbientLightRingBuffer.getTime(i);
@@ -616,20 +622,19 @@ class AutomaticBrightnessController {
float slowAmbientLux = calculateAmbientLux(time, AMBIENT_LIGHT_LONG_HORIZON_MILLIS);
float fastAmbientLux = calculateAmbientLux(time, AMBIENT_LIGHT_SHORT_HORIZON_MILLIS);
- if ((slowAmbientLux >= mBrighteningLuxThreshold &&
- fastAmbientLux >= mBrighteningLuxThreshold &&
- nextBrightenTransition <= time)
- ||
- (slowAmbientLux <= mDarkeningLuxThreshold &&
- fastAmbientLux <= mDarkeningLuxThreshold &&
- nextDarkenTransition <= time)) {
+ if ((slowAmbientLux >= mAmbientBrighteningThreshold
+ && fastAmbientLux >= mAmbientBrighteningThreshold
+ && nextBrightenTransition <= time)
+ || (slowAmbientLux <= mAmbientDarkeningThreshold
+ && fastAmbientLux <= mAmbientDarkeningThreshold
+ && nextDarkenTransition <= time)) {
setAmbientLux(fastAmbientLux);
if (DEBUG) {
Slog.d(TAG, "updateAmbientLux: " +
- ((fastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": " +
- "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold + ", " +
- "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", " +
- "mAmbientLux=" + mAmbientLux);
+ ((fastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": "
+ + "mAmbientBrighteningThreshold=" + mAmbientBrighteningThreshold + ", "
+ + "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", "
+ + "mAmbientLux=" + mAmbientLux);
}
updateAutoBrightness(true);
nextBrightenTransition = nextAmbientLightBrighteningTransition(time);
@@ -660,6 +665,20 @@ class AutomaticBrightnessController {
int newScreenAutoBrightness =
clampScreenBrightness(Math.round(value * PowerManager.BRIGHTNESS_ON));
+
+ // If mScreenAutoBrightness is set, we should have screen{Brightening,Darkening}Threshold,
+ // in which case we ignore the new screen brightness if it doesn't differ enough from the
+ // previous one.
+ if (mScreenAutoBrightness != -1
+ && newScreenAutoBrightness > mScreenDarkeningThreshold
+ && newScreenAutoBrightness < mScreenBrighteningThreshold) {
+ if (DEBUG) {
+ Slog.d(TAG, "ignoring newScreenAutoBrightness: " + mScreenDarkeningThreshold
+ + " < " + newScreenAutoBrightness + " < " + mScreenBrighteningThreshold);
+ }
+ return;
+ }
+
if (mScreenAutoBrightness != newScreenAutoBrightness) {
if (DEBUG) {
Slog.d(TAG, "updateAutoBrightness: " +
@@ -668,6 +687,11 @@ class AutomaticBrightnessController {
}
mScreenAutoBrightness = newScreenAutoBrightness;
+ mScreenBrighteningThreshold =
+ mScreenBrightnessThresholds.getBrighteningThreshold(newScreenAutoBrightness);
+ mScreenDarkeningThreshold =
+ mScreenBrightnessThresholds.getDarkeningThreshold(newScreenAutoBrightness);
+
if (sendUpdate) {
mCallbacks.updateBrightness();
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 99412c56b274..c75761ff6ece 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -16,16 +16,11 @@
package com.android.server.display;
-import android.app.ActivityManager;
-import com.android.internal.app.IBatteryStats;
-import com.android.server.LocalServices;
-import com.android.server.am.BatteryStatsService;
-import com.android.server.policy.WindowManagerPolicy;
-
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
@@ -54,6 +49,11 @@ import android.util.Slog;
import android.util.TimeUtils;
import android.view.Display;
+import com.android.internal.app.IBatteryStats;
+import com.android.server.LocalServices;
+import com.android.server.am.BatteryStatsService;
+import com.android.server.policy.WindowManagerPolicy;
+
import java.io.PrintWriter;
/**
@@ -422,14 +422,25 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
1, 1);
- int[] brightLevels = resources.getIntArray(
- com.android.internal.R.array.config_dynamicHysteresisBrightLevels);
- int[] darkLevels = resources.getIntArray(
- com.android.internal.R.array.config_dynamicHysteresisDarkLevels);
- int[] luxHysteresisLevels = resources.getIntArray(
- com.android.internal.R.array.config_dynamicHysteresisLuxLevels);
- HysteresisLevels hysteresisLevels = new HysteresisLevels(
- brightLevels, darkLevels, luxHysteresisLevels);
+ int[] ambientBrighteningThresholds = resources.getIntArray(
+ com.android.internal.R.array.config_ambientBrighteningThresholds);
+ int[] ambientDarkeningThresholds = resources.getIntArray(
+ com.android.internal.R.array.config_ambientDarkeningThresholds);
+ int[] ambientThresholdLevels = resources.getIntArray(
+ com.android.internal.R.array.config_ambientThresholdLevels);
+ HysteresisLevels ambientBrightnessThresholds = new HysteresisLevels(
+ ambientBrighteningThresholds, ambientDarkeningThresholds,
+ ambientThresholdLevels);
+
+ int[] screenBrighteningThresholds = resources.getIntArray(
+ com.android.internal.R.array.config_screenBrighteningThresholds);
+ int[] screenDarkeningThresholds = resources.getIntArray(
+ com.android.internal.R.array.config_screenDarkeningThresholds);
+ int[] screenThresholdLevels = resources.getIntArray(
+ com.android.internal.R.array.config_screenThresholdLevels);
+ HysteresisLevels screenBrightnessThresholds = new HysteresisLevels(
+ screenBrighteningThresholds, screenDarkeningThresholds, screenThresholdLevels);
+
long brighteningLightDebounce = resources.getInteger(
com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce);
@@ -459,7 +470,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
lightSensorWarmUpTimeConfig, mScreenBrightnessRangeMinimum,
mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
- autoBrightnessResetAmbientLuxAfterWarmUp, hysteresisLevels);
+ autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
+ screenBrightnessThresholds);
} else {
mUseSoftwareAutoBrightnessConfig = false;
}
@@ -791,9 +803,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
&& mAutomaticBrightnessController != null;
final boolean userSetBrightnessChanged = updateUserSetScreenBrightness();
- if (userSetBrightnessChanged) {
- mTemporaryScreenBrightness = -1;
- }
// Use the temporary screen brightness if there isn't an override, either from
// WindowManager or based on the display state.
@@ -1514,11 +1523,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
if (mCurrentScreenBrightnessSetting == mPendingScreenBrightnessSetting) {
mPendingScreenBrightnessSetting = -1;
+ mTemporaryScreenBrightness = -1;
return false;
}
mCurrentScreenBrightnessSetting = mPendingScreenBrightnessSetting;
mLastUserSetScreenBrightness = mPendingScreenBrightnessSetting;
mPendingScreenBrightnessSetting = -1;
+ mTemporaryScreenBrightness = -1;
return true;
}
diff --git a/services/core/java/com/android/server/display/HysteresisLevels.java b/services/core/java/com/android/server/display/HysteresisLevels.java
index 1c02dd1fcdf4..2db1d03893d2 100644
--- a/services/core/java/com/android/server/display/HysteresisLevels.java
+++ b/services/core/java/com/android/server/display/HysteresisLevels.java
@@ -28,67 +28,67 @@ final class HysteresisLevels {
private static final String TAG = "HysteresisLevels";
// Default hysteresis constraints for brightening or darkening.
- // The recent lux must have changed by at least this fraction relative to the
- // current ambient lux before a change will be considered.
+ // The recent value must have changed by at least this fraction relative to the
+ // current value before a change will be considered.
private static final float DEFAULT_BRIGHTENING_HYSTERESIS = 0.10f;
private static final float DEFAULT_DARKENING_HYSTERESIS = 0.20f;
private static final boolean DEBUG = false;
- private final float[] mBrightLevels;
- private final float[] mDarkLevels;
- private final float[] mLuxLevels;
+ private final float[] mBrighteningThresholds;
+ private final float[] mDarkeningThresholds;
+ private final float[] mThresholdLevels;
- /**
- * Creates a {@code HysteresisLevels} object with the given equal-length
- * integer arrays.
- * @param brightLevels an array of brightening hysteresis constraint constants
- * @param darkLevels an array of darkening hysteresis constraint constants
- * @param luxLevels a monotonically increasing array of illuminance
- * thresholds in units of lux
- */
- public HysteresisLevels(int[] brightLevels, int[] darkLevels, int[] luxLevels) {
- if (brightLevels.length != darkLevels.length || darkLevels.length != luxLevels.length + 1) {
+ /**
+ * Creates a {@code HysteresisLevels} object with the given equal-length
+ * integer arrays.
+ * @param brighteningThresholds an array of brightening hysteresis constraint constants.
+ * @param darkeningThresholds an array of darkening hysteresis constraint constants.
+ * @param thresholdLevels a monotonically increasing array of threshold levels.
+ */
+ HysteresisLevels(int[] brighteningThresholds, int[] darkeningThresholds,
+ int[] thresholdLevels) {
+ if (brighteningThresholds.length != darkeningThresholds.length
+ || darkeningThresholds.length != thresholdLevels.length + 1) {
throw new IllegalArgumentException("Mismatch between hysteresis array lengths.");
}
- mBrightLevels = setArrayFormat(brightLevels, 1000.0f);
- mDarkLevels = setArrayFormat(darkLevels, 1000.0f);
- mLuxLevels = setArrayFormat(luxLevels, 1.0f);
+ mBrighteningThresholds = setArrayFormat(brighteningThresholds, 1000.0f);
+ mDarkeningThresholds = setArrayFormat(darkeningThresholds, 1000.0f);
+ mThresholdLevels = setArrayFormat(thresholdLevels, 1.0f);
}
/**
- * Return the brightening hysteresis threshold for the given lux level.
+ * Return the brightening hysteresis threshold for the given value level.
*/
- public float getBrighteningThreshold(float lux) {
- float brightConstant = getReferenceLevel(lux, mBrightLevels);
- float brightThreshold = lux * (1.0f + brightConstant);
+ float getBrighteningThreshold(float value) {
+ float brightConstant = getReferenceLevel(value, mBrighteningThresholds);
+ float brightThreshold = value * (1.0f + brightConstant);
if (DEBUG) {
- Slog.d(TAG, "bright hysteresis constant=: " + brightConstant + ", threshold="
- + brightThreshold + ", lux=" + lux);
+ Slog.d(TAG, "bright hysteresis constant=" + brightConstant + ", threshold="
+ + brightThreshold + ", value=" + value);
}
return brightThreshold;
}
/**
- * Return the darkening hysteresis threshold for the given lux level.
+ * Return the darkening hysteresis threshold for the given value level.
*/
- public float getDarkeningThreshold(float lux) {
- float darkConstant = getReferenceLevel(lux, mDarkLevels);
- float darkThreshold = lux * (1.0f - darkConstant);
+ float getDarkeningThreshold(float value) {
+ float darkConstant = getReferenceLevel(value, mDarkeningThresholds);
+ float darkThreshold = value * (1.0f - darkConstant);
if (DEBUG) {
Slog.d(TAG, "dark hysteresis constant=: " + darkConstant + ", threshold="
- + darkThreshold + ", lux=" + lux);
+ + darkThreshold + ", value=" + value);
}
return darkThreshold;
}
/**
- * Return the hysteresis constant for the closest lux threshold value to the
- * current illuminance from the given array.
+ * Return the hysteresis constant for the closest threshold value from the given array.
*/
- private float getReferenceLevel(float lux, float[] referenceLevels) {
+ private float getReferenceLevel(float value, float[] referenceLevels) {
int index = 0;
- while (mLuxLevels.length > index && lux >= mLuxLevels[index]) {
+ while (mThresholdLevels.length > index && value >= mThresholdLevels[index]) {
++index;
}
return referenceLevels[index];
@@ -105,10 +105,10 @@ final class HysteresisLevels {
return levelArray;
}
- public void dump(PrintWriter pw) {
+ void dump(PrintWriter pw) {
pw.println("HysteresisLevels");
- pw.println(" mBrightLevels=" + Arrays.toString(mBrightLevels));
- pw.println(" mDarkLevels=" + Arrays.toString(mDarkLevels));
- pw.println(" mLuxLevels=" + Arrays.toString(mLuxLevels));
+ pw.println(" mBrighteningThresholds=" + Arrays.toString(mBrighteningThresholds));
+ pw.println(" mDarkeningThresholds=" + Arrays.toString(mDarkeningThresholds));
+ pw.println(" mThresholdLevels=" + Arrays.toString(mThresholdLevels));
}
}
diff --git a/services/core/java/com/android/server/locksettings/SP800Derive.java b/services/core/java/com/android/server/locksettings/SP800Derive.java
new file mode 100644
index 000000000000..77561fc30db9
--- /dev/null
+++ b/services/core/java/com/android/server/locksettings/SP800Derive.java
@@ -0,0 +1,82 @@
+/*
+ * 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 java.nio.ByteBuffer;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Implementation of NIST SP800-108
+ * "Recommendation for Key Derivation Using Pseudorandom Functions"
+ * Hardcoded:
+ * [PRF=HMAC_SHA256]
+ * [CTRLOCATION=BEFORE_FIXED]
+ * [RLEN=32_BITS]
+ * L = 256
+ * L suffix: 32 bits
+ */
+class SP800Derive {
+ private final byte[] mKeyBytes;
+
+ SP800Derive(byte[] keyBytes) {
+ mKeyBytes = keyBytes;
+ }
+
+ private Mac getMac() {
+ try {
+ final Mac m = Mac.getInstance("HmacSHA256");
+ m.init(new SecretKeySpec(mKeyBytes, m.getAlgorithm()));
+ return m;
+ } catch (InvalidKeyException | NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static void update32(Mac m, int v) {
+ m.update(ByteBuffer.allocate(Integer.BYTES).putInt(v).array());
+ }
+
+ /**
+ * Generate output from a single, fixed input.
+ */
+ public byte[] fixedInput(byte[] fixedInput) {
+ final Mac m = getMac();
+ update32(m, 1); // Hardwired counter value
+ m.update(fixedInput);
+ return m.doFinal();
+ }
+
+ /**
+ * Generate output from a label and context. We add a length field at the end of the context to
+ * disambiguate it from the length even in the presence of zero bytes.
+ */
+ public byte[] withContext(byte[] label, byte[] context) {
+ final Mac m = getMac();
+ // Hardwired counter value: 1
+ update32(m, 1); // Hardwired counter value
+ m.update(label);
+ m.update((byte) 0);
+ m.update(context);
+ update32(m, context.length * 8); // Disambiguate context
+ update32(m, 256); // Hardwired output length
+ return m.doFinal();
+ }
+}
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 596daeb1427b..d32c299074a9 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -26,9 +26,9 @@ import android.hardware.weaver.V1_0.WeaverConfig;
import android.hardware.weaver.V1_0.WeaverReadResponse;
import android.hardware.weaver.V1_0.WeaverReadStatus;
import android.hardware.weaver.V1_0.WeaverStatus;
-import android.security.GateKeeper;
import android.os.RemoteException;
import android.os.UserManager;
+import android.security.GateKeeper;
import android.service.gatekeeper.GateKeeperResponse;
import android.service.gatekeeper.IGateKeeperService;
import android.util.ArrayMap;
@@ -102,7 +102,8 @@ public class SyntheticPasswordManager {
private static final int INVALID_WEAVER_SLOT = -1;
private static final byte SYNTHETIC_PASSWORD_VERSION_V1 = 1;
- private static final byte SYNTHETIC_PASSWORD_VERSION = 2;
+ private static final byte SYNTHETIC_PASSWORD_VERSION_V2 = 2;
+ private static final byte SYNTHETIC_PASSWORD_VERSION_V3 = 3;
private static final byte SYNTHETIC_PASSWORD_PASSWORD_BASED = 0;
private static final byte SYNTHETIC_PASSWORD_TOKEN_BASED = 1;
@@ -128,6 +129,8 @@ public class SyntheticPasswordManager {
private static final byte[] PERSONALISATION_WEAVER_PASSWORD = "weaver-pwd".getBytes();
private static final byte[] PERSONALISATION_WEAVER_KEY = "weaver-key".getBytes();
private static final byte[] PERSONALISATION_WEAVER_TOKEN = "weaver-token".getBytes();
+ private static final byte[] PERSONALISATION_CONTEXT =
+ "android-synthetic-password-personalization-context".getBytes();
static class AuthenticationResult {
public AuthenticationToken authToken;
@@ -136,6 +139,7 @@ public class SyntheticPasswordManager {
}
static class AuthenticationToken {
+ private final byte mVersion;
/*
* Here is the relationship between all three fields:
* P0 and P1 are two randomly-generated blocks. P1 is stored on disk but P0 is not.
@@ -146,29 +150,38 @@ public class SyntheticPasswordManager {
private @Nullable byte[] P1;
private @NonNull String syntheticPassword;
+ AuthenticationToken(byte version) {
+ mVersion = version;
+ }
+
+ private byte[] derivePassword(byte[] personalization) {
+ if (mVersion == SYNTHETIC_PASSWORD_VERSION_V3) {
+ return (new SP800Derive(syntheticPassword.getBytes()))
+ .withContext(personalization, PERSONALISATION_CONTEXT);
+ } else {
+ return SyntheticPasswordCrypto.personalisedHash(personalization,
+ syntheticPassword.getBytes());
+ }
+ }
+
public String deriveKeyStorePassword() {
- return bytesToHex(SyntheticPasswordCrypto.personalisedHash(
- PERSONALIZATION_KEY_STORE_PASSWORD, syntheticPassword.getBytes()));
+ return bytesToHex(derivePassword(PERSONALIZATION_KEY_STORE_PASSWORD));
}
public byte[] deriveGkPassword() {
- return SyntheticPasswordCrypto.personalisedHash(PERSONALIZATION_SP_GK_AUTH,
- syntheticPassword.getBytes());
+ return derivePassword(PERSONALIZATION_SP_GK_AUTH);
}
public byte[] deriveDiskEncryptionKey() {
- return SyntheticPasswordCrypto.personalisedHash(PERSONALIZATION_FBE_KEY,
- syntheticPassword.getBytes());
+ return derivePassword(PERSONALIZATION_FBE_KEY);
}
public byte[] deriveVendorAuthSecret() {
- return SyntheticPasswordCrypto.personalisedHash(PERSONALIZATION_AUTHSECRET_KEY,
- syntheticPassword.getBytes());
+ return derivePassword(PERSONALIZATION_AUTHSECRET_KEY);
}
public byte[] derivePasswordHashFactor() {
- return SyntheticPasswordCrypto.personalisedHash(PERSONALIZATION_PASSWORD_HASH,
- syntheticPassword.getBytes());
+ return derivePassword(PERSONALIZATION_PASSWORD_HASH);
}
private void initialize(byte[] P0, byte[] P1) {
@@ -185,7 +198,7 @@ public class SyntheticPasswordManager {
}
protected static AuthenticationToken create() {
- AuthenticationToken result = new AuthenticationToken();
+ AuthenticationToken result = new AuthenticationToken(SYNTHETIC_PASSWORD_VERSION_V3);
result.initialize(secureRandom(SYNTHETIC_PASSWORD_LENGTH),
secureRandom(SYNTHETIC_PASSWORD_LENGTH));
return result;
@@ -802,7 +815,16 @@ public class SyntheticPasswordManager {
}
byte[] content = createSPBlob(getHandleName(handle), secret, applicationId, sid);
byte[] blob = new byte[content.length + 1 + 1];
- blob[0] = SYNTHETIC_PASSWORD_VERSION;
+ /*
+ * We can upgrade from v1 to v2 because that's just a change in the way that
+ * the SP is stored. However, we can't upgrade to v3 because that is a change
+ * in the way that passwords are derived from the SP.
+ */
+ if (authToken.mVersion == SYNTHETIC_PASSWORD_VERSION_V3) {
+ blob[0] = SYNTHETIC_PASSWORD_VERSION_V3;
+ } else {
+ blob[0] = SYNTHETIC_PASSWORD_VERSION_V2;
+ }
blob[1] = type;
System.arraycopy(content, 0, blob, 2, content.length);
saveState(SP_BLOB_NAME, blob, handle, userId);
@@ -940,7 +962,9 @@ public class SyntheticPasswordManager {
return null;
}
final byte version = blob[0];
- if (version != SYNTHETIC_PASSWORD_VERSION && version != SYNTHETIC_PASSWORD_VERSION_V1) {
+ if (version != SYNTHETIC_PASSWORD_VERSION_V3
+ && version != SYNTHETIC_PASSWORD_VERSION_V2
+ && version != SYNTHETIC_PASSWORD_VERSION_V1) {
throw new RuntimeException("Unknown blob version");
}
if (blob[1] != type) {
@@ -958,7 +982,7 @@ public class SyntheticPasswordManager {
Log.e(TAG, "Fail to decrypt SP for user " + userId);
return null;
}
- AuthenticationToken result = new AuthenticationToken();
+ AuthenticationToken result = new AuthenticationToken(version);
if (type == SYNTHETIC_PASSWORD_TOKEN_BASED) {
if (!loadEscrowData(result, userId)) {
Log.e(TAG, "User is not escrowable: " + userId);
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 547ab0ed443d..0d0004134eb6 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -541,6 +541,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
*/
private void extractColors(WallpaperData wallpaper) {
String cropFile = null;
+ boolean defaultImageWallpaper = false;
int wallpaperId;
synchronized (mLock) {
@@ -549,6 +550,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
|| wallpaper.wallpaperComponent == null;
if (imageWallpaper && wallpaper.cropFile != null && wallpaper.cropFile.exists()) {
cropFile = wallpaper.cropFile.getAbsolutePath();
+ } else if (imageWallpaper && !wallpaper.cropExists() && !wallpaper.sourceExists()) {
+ defaultImageWallpaper = true;
}
wallpaperId = wallpaper.wallpaperId;
}
@@ -560,6 +563,25 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
colors = WallpaperColors.fromBitmap(bitmap);
bitmap.recycle();
}
+ } else if (defaultImageWallpaper) {
+ // There is no crop and source file because this is default image wallpaper.
+ try (final InputStream is =
+ WallpaperManager.openDefaultWallpaper(mContext, FLAG_SYSTEM)) {
+ if (is != null) {
+ try {
+ final BitmapFactory.Options options = new BitmapFactory.Options();
+ final Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
+ if (bitmap != null) {
+ colors = WallpaperColors.fromBitmap(bitmap);
+ bitmap.recycle();
+ }
+ } catch (OutOfMemoryError e) {
+ Slog.w(TAG, "Can't decode default wallpaper stream", e);
+ }
+ }
+ } catch (IOException e) {
+ Slog.w(TAG, "Can't close default wallpaper stream", e);
+ }
}
if (colors == null) {
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SP800DeriveTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SP800DeriveTests.java
new file mode 100644
index 000000000000..fc2dcb9cc83b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SP800DeriveTests.java
@@ -0,0 +1,40 @@
+/*
+ * 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.locksettings;
+
+import android.test.AndroidTestCase;
+
+import com.android.internal.util.HexDump;
+
+public class SP800DeriveTests extends AndroidTestCase {
+ public void testFixedInput() throws Exception {
+ // CAVP: https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/key-derivation
+ byte[] keyBytes = HexDump.hexStringToByteArray(
+ "e204d6d466aad507ffaf6d6dab0a5b26"
+ + "152c9e21e764370464e360c8fbc765c6");
+ SP800Derive sk = new SP800Derive(keyBytes);
+ byte[] fixedInput = HexDump.hexStringToByteArray(
+ "7b03b98d9f94b899e591f3ef264b71b1"
+ + "93fba7043c7e953cde23bc5384bc1a62"
+ + "93580115fae3495fd845dadbd02bd645"
+ + "5cf48d0f62b33e62364a3a80");
+ byte[] res = sk.fixedInput(fixedInput);
+ assertEquals((
+ "770dfab6a6a4a4bee0257ff335213f78"
+ + "d8287b4fd537d5c1fffa956910e7c779").toUpperCase(), HexDump.toHexString(res));
+ }
+}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 806e139bba17..ef0f71ab9954 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1092,6 +1092,19 @@ public class CarrierConfigManager {
public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string";
/**
+ * String to override sim country iso.
+ * Sim country iso is based on sim MCC which is coarse and doesn't work with dual IMSI SIM where
+ * a SIM can have multiple MCC from different countries.
+ * Instead, each sim carrier should have a single country code, apply per carrier based iso
+ * code as an override. The overridden value can be read from
+ * {@link TelephonyManager#getSimCountryIso()} and {@link SubscriptionInfo#getCountryIso()}
+ *
+ * @hide
+ */
+ public static final String KEY_SIM_COUNTRY_ISO_OVERRIDE_STRING =
+ "sim_country_iso_override_string";
+
+ /**
* Override the registered PLMN name using #KEY_CDMA_HOME_REGISTERED_PLMN_NAME_STRING.
*
* If true, then the registered PLMN name (only for CDMA/CDMA-LTE and only when not roaming)
@@ -2237,6 +2250,7 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_CONFIG_WIFI_DISABLE_IN_ECBM, false);
sDefaults.putBoolean(KEY_CARRIER_NAME_OVERRIDE_BOOL, false);
sDefaults.putString(KEY_CARRIER_NAME_STRING, "");
+ sDefaults.putString(KEY_SIM_COUNTRY_ISO_OVERRIDE_STRING, "");
sDefaults.putBoolean(KEY_CDMA_HOME_REGISTERED_PLMN_NAME_OVERRIDE_BOOL, false);
sDefaults.putString(KEY_CDMA_HOME_REGISTERED_PLMN_NAME_STRING, "");
sDefaults.putBoolean(KEY_SUPPORT_DIRECT_FDN_DIALING_BOOL, false);
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 38bc64036de0..200cbc01ce5c 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -257,6 +257,15 @@ public final class SmsManager {
*/
public static final String MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER =
CarrierConfigManager.KEY_MMS_SUPPORT_HTTP_CHARSET_HEADER_BOOL;
+
+ /**
+ * When roaming, some operator's MCC would change. It results in MMSService's verification
+ * failure. This config could use correct country.
+ * @hide
+ */
+ public static final String MMS_CONFIG_SIM_COUNTRY_ISO_OVERRIDE =
+ CarrierConfigManager.KEY_SIM_COUNTRY_ISO_OVERRIDE_STRING;
+
/**
* If true, add "Connection: close" header to MMS HTTP requests so the connection
* is immediately closed (disabling keep-alive). (Boolean type)
@@ -2065,6 +2074,8 @@ public final class SmsManager {
filtered.putString(MMS_CONFIG_EMAIL_GATEWAY_NUMBER,
config.getString(MMS_CONFIG_EMAIL_GATEWAY_NUMBER));
filtered.putString(MMS_CONFIG_NAI_SUFFIX, config.getString(MMS_CONFIG_NAI_SUFFIX));
+ filtered.putString(MMS_CONFIG_SIM_COUNTRY_ISO_OVERRIDE,
+ config.getString(MMS_CONFIG_SIM_COUNTRY_ISO_OVERRIDE));
filtered.putBoolean(MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS,
config.getBoolean(MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS));
filtered.putBoolean(MMS_CONFIG_SUPPORT_HTTP_CHARSET_HEADER,
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c574fb4d6605..e7361ef66531 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -7581,6 +7581,9 @@ public class TelephonyManager {
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public int setAllowedCarriers(int slotIndex, List<CarrierIdentifier> carriers) {
+ if (!SubscriptionManager.isValidPhoneId(slotIndex)) {
+ return -1;
+ }
try {
ITelephony service = getITelephony();
if (service != null) {
@@ -7608,15 +7611,17 @@ public class TelephonyManager {
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public List<CarrierIdentifier> getAllowedCarriers(int slotIndex) {
- try {
- ITelephony service = getITelephony();
- if (service != null) {
- return service.getAllowedCarriers(slotIndex);
+ if (SubscriptionManager.isValidPhoneId(slotIndex)) {
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ return service.getAllowedCarriers(slotIndex);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#getAllowedCarriers", e);
+ } catch (NullPointerException e) {
+ Log.e(TAG, "Error calling ITelephony#getAllowedCarriers", e);
}
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#getAllowedCarriers", e);
- } catch (NullPointerException e) {
- Log.e(TAG, "Error calling ITelephony#getAllowedCarriers", e);
}
return new ArrayList<CarrierIdentifier>(0);
}