diff options
24 files changed, 255 insertions, 71 deletions
diff --git a/api/current.txt b/api/current.txt index e295a63..cb63aaa 100644 --- a/api/current.txt +++ b/api/current.txt @@ -106,6 +106,7 @@ package android { field public static final java.lang.String RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH"; field public static final java.lang.String RECORD_AUDIO = "android.permission.RECORD_AUDIO"; field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS"; + field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES"; field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES"; field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE"; @@ -26444,6 +26445,7 @@ package android.provider { field public static final java.lang.String ACTION_PRINT_SETTINGS = "android.settings.ACTION_PRINT_SETTINGS"; field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS"; field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS"; + field public static final java.lang.String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS"; field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS"; field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS"; @@ -33956,6 +33958,7 @@ package android.util { field public static final int DENSITY_280 = 280; // 0x118 field public static final int DENSITY_360 = 360; // 0x168 field public static final int DENSITY_400 = 400; // 0x190 + field public static final int DENSITY_420 = 420; // 0x1a4 field public static final int DENSITY_560 = 560; // 0x230 field public static final int DENSITY_DEFAULT = 160; // 0xa0 field public static final int DENSITY_HIGH = 240; // 0xf0 diff --git a/api/system-current.txt b/api/system-current.txt index 8b9af5e..a9bc944 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -180,6 +180,7 @@ package android { field public static final java.lang.String REGISTER_SIM_SUBSCRIPTION = "android.permission.REGISTER_SIM_SUBSCRIPTION"; field public static final java.lang.String REMOVE_DRM_CERTIFICATES = "android.permission.REMOVE_DRM_CERTIFICATES"; field public static final java.lang.String REORDER_TASKS = "android.permission.REORDER_TASKS"; + field public static final java.lang.String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES"; field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES"; field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT"; @@ -28502,6 +28503,7 @@ package android.provider { field public static final java.lang.String ACTION_PRINT_SETTINGS = "android.settings.ACTION_PRINT_SETTINGS"; field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS"; field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS"; + field public static final java.lang.String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS"; field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS"; field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS"; @@ -36248,6 +36250,7 @@ package android.util { field public static final int DENSITY_280 = 280; // 0x118 field public static final int DENSITY_360 = 360; // 0x168 field public static final int DENSITY_400 = 400; // 0x190 + field public static final int DENSITY_420 = 420; // 0x1a4 field public static final int DENSITY_560 = 560; // 0x230 field public static final int DENSITY_DEFAULT = 160; // 0xa0 field public static final int DENSITY_HIGH = 240; // 0xf0 diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index fd88a05..da21eaf 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -4235,11 +4235,6 @@ public final class ActivityThread { configDiff = mConfiguration.updateFrom(config); config = applyCompatConfiguration(mCurDefaultDisplayDpi); - - final Theme systemTheme = getSystemContext().getTheme(); - if ((systemTheme.getChangingConfigurations() & configDiff) != 0) { - systemTheme.rebase(); - } } ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config); diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java index abe12dc..7824072 100644 --- a/core/java/android/app/AlertDialog.java +++ b/core/java/android/app/AlertDialog.java @@ -1082,7 +1082,8 @@ public class AlertDialog extends Dialog implements DialogInterface { * create and display the dialog. */ public AlertDialog create() { - final AlertDialog dialog = new AlertDialog(P.mContext); + // Context has already been wrapped with the appropriate theme. + final AlertDialog dialog = new AlertDialog(P.mContext, 0, false); P.apply(dialog.mAlert); dialog.setCancelable(P.mCancelable); if (P.mCancelable) { diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index c505b0b..e3414d9 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -3204,8 +3204,13 @@ public class DevicePolicyManager { * Called by a profile or device owner to set the application restrictions for a given target * application running in the profile. * - * <p>The provided {@link Bundle} consists of key-value pairs, where the types of values may be - * boolean, int, String, or String[]. + * <p>The provided {@link Bundle} consists of key-value pairs, where the types of values may be: + * <ul> + * <li>{@code boolean} + * <li>{@code int} + * <li>{@code String} or {@code String[]} + * <li>From {@link android.os.Build.VERSION_CODES#M}, {@code Bundle} or {@code Bundle[]} + * </ul> * * <p>The application restrictions are only made visible to the target application and the * profile or device owner. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 6e178a4..fe95864 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -616,20 +616,46 @@ public final class Settings { /** * Activity Action: Show screen for controlling which apps can ignore battery optimizations. * <p> - * Input: Optionally, the Intent's data URI specifies the application package name - * to be shown, with the "package" scheme. That is "package:com.my.app". + * Input: Nothing. * <p> * Output: Nothing. * <p> * You can use {@link android.os.PowerManager#isIgnoringBatteryOptimizations * PowerManager.isIgnoringBatteryOptimizations()} to determine if an application is - * already ignoring optimizations. + * already ignoring optimizations. You can use + * {@link #ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS} to ask the user to put you + * on this list. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS = "android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS"; /** + * Activity Action: Ask the user to allow an to ignore battery optimizations (that is, + * put them on the whitelist of apps shown by + * {@link #ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS}). For an app to use this, it also + * must hold the {@link android.Manifest.permission#REQUEST_IGNORE_BATTERY_OPTIMIZATIONS} + * permission. + * <p><b>Note:</b> most applications should <em>not</em> use this; there are many facilities + * provided by the platform for applications to operate correctly in the various power + * saving mode. This is only for unusual applications that need to deeply control their own + * execution, at the potential expense of the user's battery life. Note that these applications + * greatly run the risk of showing to the user has how power consumers on their device.</p> + * <p> + * Input: The Intent's data URI must specify the application package name + * to be shown, with the "package" scheme. That is "package:com.my.app". + * <p> + * Output: Nothing. + * <p> + * You can use {@link android.os.PowerManager#isIgnoringBatteryOptimizations + * PowerManager.isIgnoringBatteryOptimizations()} to determine if an application is + * already ignoring optimizations. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = + "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; + + /** * @hide * Activity Action: Show the "app ops" settings screen. * <p> diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java index a36e66c..9a69600 100644 --- a/core/java/android/util/DisplayMetrics.java +++ b/core/java/android/util/DisplayMetrics.java @@ -90,6 +90,14 @@ public class DisplayMetrics { public static final int DENSITY_400 = 400; /** + * Intermediate density for screens that sit somewhere between + * {@link #DENSITY_XHIGH} (320 dpi) and {@link #DENSITY_XXHIGH} (480 dpi). + * This is not a density that applications should target, instead relying + * on the system to scale their {@link #DENSITY_XXHIGH} assets for them. + */ + public static final int DENSITY_420 = 420; + + /** * Standard quantized DPI for extra-extra-high-density screens. */ public static final int DENSITY_XXHIGH = 480; diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 5e5450e..6b07a47 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -269,6 +269,10 @@ LOCAL_CFLAGS += -Wall -Werror -Wno-error=deprecated-declarations -Wunused -Wunre # is not being compiled with that level. Remove once this has changed. LOCAL_CFLAGS += -Wno-c++11-extensions +# b/22414716: thread_local (android/graphics/Paint.cpp) and Clang don't like each other at the +# moment. +LOCAL_CLANG := false + include $(BUILD_SHARED_LIBRARY) include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 53b553e8..629d14b 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2257,6 +2257,13 @@ <permission android:name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST" android:protectionLevel="system|signature" /> + <!-- Permission an application must hold in order to use + {@link android.provider.Settings#ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}. + This is a normal permission: an app requesting it will always be granted the + permission, without the user needing to approve or see it. --> + <permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" + android:protectionLevel="normal" /> + <!-- @SystemApi Allows an application to collect battery statistics --> <permission android:name="android.permission.BATTERY_STATS" android:protectionLevel="signature|privileged|development" /> diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index bf069d3..32f6a89 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -786,12 +786,16 @@ public class RippleDrawable extends LayerDrawable { mMaskColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_IN); } - // Draw the appropriate mask. + // Draw the appropriate mask anchored to (0,0). + final int left = bounds.left; + final int top = bounds.top; + mMaskCanvas.translate(-left, -top); if (maskType == MASK_EXPLICIT) { drawMask(mMaskCanvas); } else if (maskType == MASK_CONTENT) { drawContent(mMaskCanvas); } + mMaskCanvas.translate(left, top); } private int getMaskType() { diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java index e74334b..b9a9c24 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java @@ -148,7 +148,10 @@ public class SettingsBackupAgent extends BackupAgentHelper { private WifiManager mWfm; private static String mWifiConfigFile; + // Chain of asynchronous operations used when rewriting the wifi supplicant config file + WifiDisableRunnable mWifiDisable = null; WifiRestoreRunnable mWifiRestore = null; + int mRetainedWifiState; // used only during config file rewrite // Class for capturing a network definition from the wifi supplicant config file static class Network { @@ -407,9 +410,47 @@ public class SettingsBackupAgent extends BackupAgentHelper { writeNewChecksums(stateChecksums, newState); } + class WifiDisableRunnable implements Runnable { + final WifiRestoreRunnable mNextPhase; + + public WifiDisableRunnable(WifiRestoreRunnable next) { + mNextPhase = next; + } + + @Override + public void run() { + if (DEBUG_BACKUP) { + Log.v(TAG, "Disabling wifi during restore"); + } + final ContentResolver cr = getContentResolver(); + final int scanAlways = Settings.Global.getInt(cr, + Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0); + final int retainedWifiState = enableWifi(false); + if (scanAlways != 0) { + Settings.Global.putInt(cr, + Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0); + } + + // Tell the final stage how to clean up after itself + mNextPhase.setPriorState(retainedWifiState, scanAlways); + + // And run it after a modest pause to give broadcasts and content + // observers time an opportunity to run on this looper thread, so + // that the wifi stack actually goes all the way down. + new Handler(getMainLooper()).postDelayed(mNextPhase, 2500); + } + } + class WifiRestoreRunnable implements Runnable { private byte[] restoredSupplicantData; private byte[] restoredWifiConfigFile; + private int retainedWifiState; // provided by disable stage + private int scanAlways; // provided by disable stage + + void setPriorState(int retainedState, int always) { + retainedWifiState = retainedState; + scanAlways = always; + } void incorporateWifiSupplicant(BackupDataInput data) { restoredSupplicantData = new byte[data.getDataSize()]; @@ -437,20 +478,8 @@ public class SettingsBackupAgent extends BackupAgentHelper { public void run() { if (restoredSupplicantData != null || restoredWifiConfigFile != null) { if (DEBUG_BACKUP) { - Log.v(TAG, "Starting deferred restore of wifi data"); - } - final ContentResolver cr = getContentResolver(); - final int scanAlways = Settings.Global.getInt(cr, - Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0); - final int retainedWifiState = enableWifi(false); - if (scanAlways != 0) { - Settings.Global.putInt(cr, - Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0); + Log.v(TAG, "Applying restored wifi data"); } - // !!! Give the wifi stack a moment to quiesce. We've observed the - // response to disabling WIFI_SCAN_ALWAYS_AVAILABLE taking more - // than 1500ms, so we wait a generous 2500 here before proceeding. - try { Thread.sleep(2500); } catch (InterruptedException e) {} if (restoredSupplicantData != null) { restoreWifiSupplicant(FILE_WIFI_SUPPLICANT, restoredSupplicantData, restoredSupplicantData.length); @@ -465,7 +494,7 @@ public class SettingsBackupAgent extends BackupAgentHelper { } // restore the previous WIFI state. if (scanAlways != 0) { - Settings.Global.putInt(cr, + Settings.Global.putInt(getContentResolver(), Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, scanAlways); } enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED || @@ -479,6 +508,7 @@ public class SettingsBackupAgent extends BackupAgentHelper { void initWifiRestoreIfNecessary() { if (mWifiRestore == null) { mWifiRestore = new WifiRestoreRunnable(); + mWifiDisable = new WifiDisableRunnable(mWifiRestore); } } @@ -518,13 +548,16 @@ public class SettingsBackupAgent extends BackupAgentHelper { } // If we have wifi data to restore, post a runnable to perform the - // bounce-and-update operation a little ways in the future. + // bounce-and-update operation a little ways in the future. The + // 'disable' runnable brings down the stack and remembers its state, + // and in turn schedules the 'restore' runnable to do the rewrite + // and cleanup operations. if (mWifiRestore != null) { long wifiBounceDelayMillis = Settings.Global.getLong( getContentResolver(), Settings.Global.WIFI_BOUNCE_DELAY_OVERRIDE_MS, WIFI_BOUNCE_DELAY_MILLIS); - new Handler(getMainLooper()).postDelayed(mWifiRestore, wifiBounceDelayMillis); + new Handler(getMainLooper()).postDelayed(mWifiDisable, wifiBounceDelayMillis); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index abdebf3..0068f84 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -1121,9 +1121,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal mViewPool.returnViewToPool(tv); } - // Notify the callback that we've removed the task and it can clean up after it - mCb.onTaskViewDismissed(removedTask); - // Get the stack scroll of the task to anchor to (since we are removing something, the front // most task will be our anchor task) Task anchorTask = null; @@ -1172,6 +1169,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // Fade the dismiss button back in showDismissAllButton(); } + + // Notify the callback that we've removed the task and it can clean up after it. Note, we + // do this after onAllTaskViewsDismissed() is called, to allow the home activity to be + // started before the call to remove the task. + mCb.onTaskViewDismissed(removedTask); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 00fa653..7065343 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -41,6 +41,7 @@ import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; @@ -1713,10 +1714,16 @@ public abstract class BaseStatusBar extends SystemUI implements sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), n); iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + final Icon smallIcon = n.getSmallIcon(); + if (smallIcon == null) { + handleNotificationError(sbn, + "No small icon in notification from " + sbn.getPackageName()); + return null; + } final StatusBarIcon ic = new StatusBarIcon( sbn.getUser(), sbn.getPackageName(), - n.getSmallIcon(), + smallIcon, n.iconLevel, n.number, n.tickerText); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 6627360..42a2f90 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -29,6 +29,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; +import android.hardware.fingerprint.FingerprintManager; import android.os.AsyncTask; import android.os.Bundle; import android.os.IBinder; @@ -601,6 +602,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } private final BroadcastReceiver mDevicePolicyReceiver = new BroadcastReceiver() { + @Override public void onReceive(Context context, Intent intent) { post(new Runnable() { @Override @@ -671,7 +673,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL @Override public void onFingerprintError(int msgId, String errString) { - if (!KeyguardUpdateMonitor.getInstance(mContext).isUnlockingWithFingerprintAllowed()) { + if (!KeyguardUpdateMonitor.getInstance(mContext).isUnlockingWithFingerprintAllowed() + || msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) { return; } // TODO: Go to bouncer if this is "too many attempts" (lockout) error. diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index 30680ed..fa87270 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -2905,9 +2905,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } // Now that we've told the host, push out an update. sendUpdateIntentLocked(provider, appWidgetIds); - providersUpdated = true; } } + providersUpdated = true; } } } diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 83e8db0..aab6374 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -2604,7 +2604,8 @@ public class AccountManagerService // Prune the list down to just the requested type. visibleAccountTypes = new ArrayList<>(); visibleAccountTypes.add(type); - } // else aggregate all the visible accounts (it won't matter if the list is empty). + } // else aggregate all the visible accounts (it won't matter if the + // list is empty). long identityToken = clearCallingIdentity(); try { @@ -3788,8 +3789,15 @@ public class AccountManagerService private List<String> getTypesForCaller( int callingUid, int userId, boolean isOtherwisePermitted) { List<String> managedAccountTypes = new ArrayList<>(); + long identityToken = Binder.clearCallingIdentity(); + Collection<RegisteredServicesCache.ServiceInfo<AuthenticatorDescription>> serviceInfos; + try { + serviceInfos = mAuthenticatorCache.getAllServices(userId); + } finally { + Binder.restoreCallingIdentity(identityToken); + } for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo : - mAuthenticatorCache.getAllServices(userId)) { + serviceInfos) { final int sigChk = mPackageManager.checkSignatures(serviceInfo.uid, callingUid); if (isOtherwisePermitted || sigChk == PackageManager.SIGNATURE_MATCH) { managedAccountTypes.add(serviceInfo.type.type); diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index a75cc48..6e34876 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -3740,7 +3740,12 @@ final class ActivityStack { if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to back transition: task=" + taskId); boolean prevIsHome = false; - if (tr.isOverHomeStack()) { + + // If true, we should resume the home activity next if the task we are moving to the + // back is over the home stack. We force to false if the task we are moving to back + // is the home task and we don't want it resumed after moving to the back. + final boolean canGoHome = !tr.isHomeTask() && tr.isOverHomeStack(); + if (canGoHome) { final TaskRecord nextTask = getNextTask(tr); if (nextTask != null) { nextTask.setTaskToReturnTo(tr.getTaskToReturnTo()); @@ -3774,8 +3779,7 @@ final class ActivityStack { } final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null; - if (prevIsHome || task == tr && tr.isOverHomeStack() - || numTasks <= 1 && isOnHomeDisplay()) { + if (prevIsHome || (task == tr && canGoHome) || (numTasks <= 1 && isOnHomeDisplay())) { if (!mService.mBooting && !mService.mBooted) { // Not ready yet! return false; diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index c705fbf..2c9d82b 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -454,6 +454,18 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe "Must have " + permission + " permission."); } + int getEffectiveUserId(int userId) { + UserManager um = UserManager.get(mContext); + if (um != null) { + final long callingIdentity = Binder.clearCallingIdentity(); + userId = um.getCredentialOwnerProfile(userId); + Binder.restoreCallingIdentity(callingIdentity); + } else { + Slog.e(TAG, "Unable to acquire UserManager"); + } + return userId; + } + boolean isCurrentUserOrProfile(int userId) { UserManager um = UserManager.get(mContext); @@ -686,11 +698,15 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe } final byte [] cryptoClone = Arrays.copyOf(cryptoToken, cryptoToken.length); + // Group ID is arbitrarily set to parent profile user ID. It just represents + // the default fingerprints for the user. + final int effectiveGroupId = getEffectiveUserId(groupId); + final boolean restricted = isRestricted(); mHandler.post(new Runnable() { @Override public void run() { - startEnrollment(token, cryptoClone, groupId, receiver, flags, restricted); + startEnrollment(token, cryptoClone, effectiveGroupId, receiver, flags, restricted); } }); } @@ -724,11 +740,16 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe Slog.w(TAG, "Calling not granted permission to use fingerprint"); return; } + + // Group ID is arbitrarily set to parent profile user ID. It just represents + // the default fingerprints for the user. + final int effectiveGroupId = getEffectiveUserId(groupId); + final boolean restricted = isRestricted(); mHandler.post(new Runnable() { @Override public void run() { - startAuthentication(token, opId, groupId, receiver, flags, restricted); + startAuthentication(token, opId, effectiveGroupId, receiver, flags, restricted); } }); } @@ -751,10 +772,14 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe final IFingerprintServiceReceiver receiver) { checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission final boolean restricted = isRestricted(); + + // Group ID is arbitrarily set to parent profile user ID. It just represents + // the default fingerprints for the user. + final int effectiveGroupId = getEffectiveUserId(groupId); mHandler.post(new Runnable() { @Override public void run() { - startRemove(token, fingerId, groupId, receiver, restricted); + startRemove(token, fingerId, effectiveGroupId, receiver, restricted); } }); @@ -771,10 +796,15 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe @Override // Binder call public void rename(final int fingerId, final int groupId, final String name) { checkPermission(MANAGE_FINGERPRINT); + + // Group ID is arbitrarily set to parent profile user ID. It just represents + // the default fingerprints for the user. + final int effectiveGroupId = getEffectiveUserId(groupId); mHandler.post(new Runnable() { @Override public void run() { - mFingerprintUtils.renameFingerprintForUser(mContext, fingerId, groupId, name); + mFingerprintUtils.renameFingerprintForUser(mContext, fingerId, + effectiveGroupId, name); } }); } @@ -784,15 +814,19 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe if (!canUseFingerprint(opPackageName)) { return Collections.emptyList(); } - return FingerprintService.this.getEnrolledFingerprints(userId); + int effectiveUserId = getEffectiveUserId(userId); + + return FingerprintService.this.getEnrolledFingerprints(effectiveUserId); } @Override // Binder call - public boolean hasEnrolledFingerprints(int groupId, String opPackageName) { + public boolean hasEnrolledFingerprints(int userId, String opPackageName) { if (!canUseFingerprint(opPackageName)) { return false; } - return FingerprintService.this.hasEnrolledFingerprints(groupId); + + int effectiveUserId = getEffectiveUserId(userId); + return FingerprintService.this.hasEnrolledFingerprints(effectiveUserId); } @Override // Binder call @@ -829,8 +863,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe IFingerprintDaemon daemon = getFingerprintDaemon(); if (daemon != null) { try { - // TODO: if this is a managed profile, use the profile parent's directory for - // storage. + userId = getEffectiveUserId(userId); final File systemDir = Environment.getUserSystemDirectory(userId); final File fpDir = new File(systemDir, FP_DATA_DIR); if (!fpDir.exists()) { diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java index 8e2ca18..92df851 100644 --- a/services/core/java/com/android/server/job/controllers/IdleController.java +++ b/services/core/java/com/android/server/job/controllers/IdleController.java @@ -108,6 +108,7 @@ public class IdleController extends StateController { private AlarmManager mAlarm; private PendingIntent mIdleTriggerIntent; boolean mIdle; + boolean mScreenOn; public IdlenessTracker() { mAlarm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); @@ -120,6 +121,7 @@ public class IdleController extends StateController { // At boot we presume that the user has just "interacted" with the // device in some meaningful way. mIdle = false; + mScreenOn = true; } public boolean isIdle() { @@ -149,12 +151,14 @@ public class IdleController extends StateController { if (action.equals(Intent.ACTION_SCREEN_ON) || action.equals(Intent.ACTION_DREAMING_STOPPED)) { - // possible transition to not-idle + if (DEBUG) { + Slog.v(TAG,"exiting idle : " + action); + } + mScreenOn = true; + //cancel the alarm + mAlarm.cancel(mIdleTriggerIntent); if (mIdle) { - if (DEBUG) { - Slog.v(TAG, "exiting idle : " + action); - } - mAlarm.cancel(mIdleTriggerIntent); + // possible transition to not-idle mIdle = false; reportNewIdleState(mIdle); } @@ -169,11 +173,12 @@ public class IdleController extends StateController { Slog.v(TAG, "Scheduling idle : " + action + " now:" + nowElapsed + " when=" + when); } + mScreenOn = false; mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, IDLE_WINDOW_SLOP, mIdleTriggerIntent); } else if (action.equals(ACTION_TRIGGER_IDLE)) { - // idle time starts now - if (!mIdle) { + // idle time starts now. Do not set mIdle if screen is on. + if (!mIdle && !mScreenOn) { if (DEBUG) { Slog.v(TAG, "Idle trigger fired @ " + SystemClock.elapsedRealtime()); } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 014527b..eb02199 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1024,12 +1024,6 @@ public final class SystemServer { w.getDefaultDisplay().getMetrics(metrics); context.getResources().updateConfiguration(config, metrics); - // The system context's theme may be configuration-dependent. - final Theme systemTheme = context.getTheme(); - if (systemTheme.getChangingConfigurations() != 0) { - systemTheme.rebase(); - } - try { // TODO: use boot phase mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService()); diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 303a492..80515cf 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -220,6 +220,8 @@ public class ServiceState implements Parcelable { private int mCdmaEriIconIndex; private int mCdmaEriIconMode; + private boolean mIsDataRoamingFromRegistration; + /** * get String description of roaming type * @hide @@ -297,6 +299,7 @@ public class ServiceState implements Parcelable { mCdmaEriIconIndex = s.mCdmaEriIconIndex; mCdmaEriIconMode = s.mCdmaEriIconMode; mIsEmergencyOnly = s.mIsEmergencyOnly; + mIsDataRoamingFromRegistration = s.mIsDataRoamingFromRegistration; } /** @@ -324,6 +327,7 @@ public class ServiceState implements Parcelable { mCdmaEriIconIndex = in.readInt(); mCdmaEriIconMode = in.readInt(); mIsEmergencyOnly = in.readInt() != 0; + mIsDataRoamingFromRegistration = in.readInt() != 0; } public void writeToParcel(Parcel out, int flags) { @@ -348,6 +352,7 @@ public class ServiceState implements Parcelable { out.writeInt(mCdmaEriIconIndex); out.writeInt(mCdmaEriIconMode); out.writeInt(mIsEmergencyOnly ? 1 : 0); + out.writeInt(mIsDataRoamingFromRegistration ? 1 : 0); } public int describeContents() { @@ -439,6 +444,26 @@ public class ServiceState implements Parcelable { } /** + * Set whether data network registration state is roaming + * + * This should only be set to the roaming value received + * once the data registration phase has completed. + * @hide + */ + public void setDataRoamingFromRegistration(boolean dataRoaming) { + mIsDataRoamingFromRegistration = dataRoaming; + } + + /** + * Get whether data network registration state is roaming + * @return true if registration indicates roaming, false otherwise + * @hide + */ + public boolean getDataRoamingFromRegistration() { + return mIsDataRoamingFromRegistration; + } + + /** * Get current data network roaming type * @return roaming type * @hide @@ -599,7 +624,8 @@ public class ServiceState implements Parcelable { + ((null == mDataOperatorNumeric) ? 0 : mDataOperatorNumeric.hashCode()) + mCdmaRoamingIndicator + mCdmaDefaultRoamingIndicator - + (mIsEmergencyOnly ? 1 : 0)); + + (mIsEmergencyOnly ? 1 : 0) + + (mIsDataRoamingFromRegistration ? 1 : 0)); } @Override @@ -635,7 +661,8 @@ public class ServiceState implements Parcelable { && equalsHandlesNulls(mCdmaRoamingIndicator, s.mCdmaRoamingIndicator) && equalsHandlesNulls(mCdmaDefaultRoamingIndicator, s.mCdmaDefaultRoamingIndicator) - && mIsEmergencyOnly == s.mIsEmergencyOnly); + && mIsEmergencyOnly == s.mIsEmergencyOnly + && mIsDataRoamingFromRegistration == s.mIsDataRoamingFromRegistration); } /** @@ -736,7 +763,8 @@ public class ServiceState implements Parcelable { + " " + mSystemId + " RoamInd=" + mCdmaRoamingIndicator + " DefRoamInd=" + mCdmaDefaultRoamingIndicator - + " EmergOnly=" + mIsEmergencyOnly); + + " EmergOnly=" + mIsEmergencyOnly + + " IsDataRoamingFromRegistration=" + mIsDataRoamingFromRegistration); } private void setNullState(int state) { @@ -762,6 +790,7 @@ public class ServiceState implements Parcelable { mCdmaEriIconIndex = -1; mCdmaEriIconMode = -1; mIsEmergencyOnly = false; + mIsDataRoamingFromRegistration = false; } public void setStateOutOfService() { @@ -934,6 +963,7 @@ public class ServiceState implements Parcelable { mCdmaRoamingIndicator = m.getInt("cdmaRoamingIndicator"); mCdmaDefaultRoamingIndicator = m.getInt("cdmaDefaultRoamingIndicator"); mIsEmergencyOnly = m.getBoolean("emergencyOnly"); + mIsDataRoamingFromRegistration = m.getBoolean("isDataRoamingFromRegistration"); } /** @@ -962,6 +992,7 @@ public class ServiceState implements Parcelable { m.putInt("cdmaRoamingIndicator", mCdmaRoamingIndicator); m.putInt("cdmaDefaultRoamingIndicator", mCdmaDefaultRoamingIndicator); m.putBoolean("emergencyOnly", Boolean.valueOf(mIsEmergencyOnly)); + m.putBoolean("isDataRoamingFromRegistration", Boolean.valueOf(mIsDataRoamingFromRegistration)); } /** @hide */ diff --git a/tests/ActivityTests/AndroidManifest.xml b/tests/ActivityTests/AndroidManifest.xml index 73cb432..7b9c9f1 100644 --- a/tests/ActivityTests/AndroidManifest.xml +++ b/tests/ActivityTests/AndroidManifest.xml @@ -24,6 +24,7 @@ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="android.permission.MANAGE_USERS" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> + <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <uses-sdk android:targetSdkVersion="22" /> <application android:label="ActivityTest"> <activity android:name="ActivityTestMain"> diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java index 2f0bf39..5fbfe8a 100644 --- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java +++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java @@ -465,9 +465,12 @@ public class ActivityTestMain extends Activity { menu.add("Ignore battery optimizations").setOnMenuItemClickListener( new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { - Intent intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS); + Intent intent; if (!mPower.isIgnoringBatteryOptimizations(getPackageName())) { + intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); intent.setData(Uri.fromParts("package", getPackageName(), null)); + } else { + intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS); } startActivity(intent); return true; diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java index 47258b6..baf2e2e 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java @@ -97,13 +97,13 @@ public final class DelegateManager<T> { * @return the delegate or null if not found. */ @Nullable - public T getDelegate(long native_object) { + public synchronized T getDelegate(long native_object) { if (native_object > 0) { - T delegate = mDelegates.get(native_object); + T delegate = mDelegates.get(native_object); if (Debug.DEBUG) { if (delegate == null) { - System.out.println("Unknown " + mClass.getSimpleName() + " with int " + + System.err.println("Unknown " + mClass.getSimpleName() + " with int " + native_object); } } @@ -119,14 +119,18 @@ public final class DelegateManager<T> { * @param newDelegate the delegate to add * @return a unique native int to identify the delegate */ - public long addNewDelegate(T newDelegate) { + public synchronized long addNewDelegate(T newDelegate) { long native_object = ++mDelegateCounter; + mDelegates.put(native_object, newDelegate); assert !mJavaReferences.contains(newDelegate); mJavaReferences.add(newDelegate); if (Debug.DEBUG) { - System.out.println("New " + mClass.getSimpleName() + " with int " + native_object); + System.out.println( + "New " + mClass.getSimpleName() + " " + + "with int " + + native_object); } return native_object; @@ -136,7 +140,7 @@ public final class DelegateManager<T> { * Removes the main reference on the given delegate. * @param native_object the native integer representing the delegate. */ - public void removeJavaReferenceFor(long native_object) { + public synchronized void removeJavaReferenceFor(long native_object) { T delegate = getDelegate(native_object); if (Debug.DEBUG) { |