summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityManager.java30
-rw-r--r--core/java/android/app/ActivityThread.java12
-rw-r--r--core/java/android/app/AlarmManager.java63
-rw-r--r--core/java/android/app/AlertDialog.java18
-rw-r--r--core/java/android/app/Dialog.java46
-rw-r--r--core/java/android/app/IAlarmManager.aidl2
-rw-r--r--core/java/android/app/INotificationManager.aidl8
-rw-r--r--core/java/android/app/NotificationManager.java31
-rw-r--r--core/java/android/app/VoiceInteractor.java2
-rw-r--r--core/java/android/app/backup/BackupManager.java26
-rw-r--r--core/java/android/app/backup/IBackupManager.aidl13
-rw-r--r--core/java/android/content/IntentFilter.java37
-rw-r--r--core/java/android/content/pm/IntentFilterVerificationInfo.java2
-rw-r--r--core/java/android/content/pm/PackageParser.java4
-rw-r--r--core/java/android/content/pm/ResolveInfo.java10
-rw-r--r--core/java/android/database/AbstractCursor.java90
-rw-r--r--core/java/android/database/BulkCursorToCursorAdaptor.java1
-rw-r--r--core/java/android/database/Cursor.java7
-rw-r--r--core/java/android/database/CursorWrapper.java55
-rw-r--r--core/java/android/database/sqlite/SQLiteCursor.java1
-rw-r--r--core/java/android/os/BatteryManager.java39
-rw-r--r--core/java/android/os/BatteryStats.java2
-rw-r--r--core/java/android/provider/Settings.java21
-rw-r--r--core/java/android/security/keymaster/KeymasterDefs.java20
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java691
-rw-r--r--core/java/android/text/method/AllCapsTransformationMethod.java21
-rw-r--r--core/java/android/text/method/BaseKeyListener.java76
-rw-r--r--core/java/android/transition/TransitionManager.java1
-rw-r--r--core/java/android/view/InputDevice.java39
-rw-r--r--core/java/android/widget/ActionMenuPresenter.java2
-rw-r--r--core/java/android/widget/Editor.java8
-rw-r--r--core/java/android/widget/FastScroller.java142
-rw-r--r--core/java/android/widget/TextView.java6
33 files changed, 1077 insertions, 449 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 8f125d7..2b35cd4 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -269,45 +269,51 @@ public class ActivityManager {
* all activities that are visible to the user. */
public static final int PROCESS_STATE_TOP = 2;
+ /** @hide Process is hosting a foreground service. */
+ public static final int PROCESS_STATE_FOREGROUND_SERVICE = 3;
+
+ /** @hide Same as {@link #PROCESS_STATE_TOP} but while device is sleeping. */
+ public static final int PROCESS_STATE_TOP_SLEEPING = 4;
+
/** @hide Process is important to the user, and something they are aware of. */
- public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 3;
+ public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 5;
/** @hide Process is important to the user, but not something they are aware of. */
- public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 4;
+ public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 6;
/** @hide Process is in the background running a backup/restore operation. */
- public static final int PROCESS_STATE_BACKUP = 5;
+ public static final int PROCESS_STATE_BACKUP = 7;
/** @hide Process is in the background, but it can't restore its state so we want
* to try to avoid killing it. */
- public static final int PROCESS_STATE_HEAVY_WEIGHT = 6;
+ public static final int PROCESS_STATE_HEAVY_WEIGHT = 8;
/** @hide Process is in the background running a service. Unlike oom_adj, this level
* is used for both the normal running in background state and the executing
* operations state. */
- public static final int PROCESS_STATE_SERVICE = 7;
+ public static final int PROCESS_STATE_SERVICE = 9;
/** @hide Process is in the background running a receiver. Note that from the
* perspective of oom_adj receivers run at a higher foreground level, but for our
* prioritization here that is not necessary and putting them below services means
* many fewer changes in some process states as they receive broadcasts. */
- public static final int PROCESS_STATE_RECEIVER = 8;
+ public static final int PROCESS_STATE_RECEIVER = 10;
/** @hide Process is in the background but hosts the home activity. */
- public static final int PROCESS_STATE_HOME = 9;
+ public static final int PROCESS_STATE_HOME = 11;
/** @hide Process is in the background but hosts the last shown activity. */
- public static final int PROCESS_STATE_LAST_ACTIVITY = 10;
+ public static final int PROCESS_STATE_LAST_ACTIVITY = 12;
/** @hide Process is being cached for later use and contains activities. */
- public static final int PROCESS_STATE_CACHED_ACTIVITY = 11;
+ public static final int PROCESS_STATE_CACHED_ACTIVITY = 13;
/** @hide Process is being cached for later use and is a client of another cached
* process that contains activities. */
- public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 12;
+ public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 14;
/** @hide Process is being cached for later use and is empty. */
- public static final int PROCESS_STATE_CACHED_EMPTY = 13;
+ public static final int PROCESS_STATE_CACHED_EMPTY = 15;
/** @hide requestType for assist context: only basic information. */
public static final int ASSIST_CONTEXT_BASIC = 0;
@@ -2064,7 +2070,7 @@ public class ActivityManager {
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
} else if (procState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
- } else if (procState >= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
+ } else if (procState >= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
} else {
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index ed05321..3b96fd5 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5322,19 +5322,25 @@ public final class ActivityThread {
private DropBoxManager dropBox;
- public DropBoxReporter() {
- dropBox = (DropBoxManager) getSystemContext().getSystemService(Context.DROPBOX_SERVICE);
- }
+ public DropBoxReporter() {}
@Override
public void addData(String tag, byte[] data, int flags) {
+ ensureInitialized();
dropBox.addData(tag, data, flags);
}
@Override
public void addText(String tag, String data) {
+ ensureInitialized();
dropBox.addText(tag, data);
}
+
+ private synchronized void ensureInitialized() {
+ if (dropBox == null) {
+ dropBox = (DropBoxManager) getSystemContext().getSystemService(Context.DROPBOX_SERVICE);
+ }
+ }
}
public static void main(String[] args) {
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 5dd02ae..179957d 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -115,6 +115,40 @@ public class AlarmManager
/** @hide */
public static final long WINDOW_HEURISTIC = -1;
+ /**
+ * Flag for alarms: this is to be a stand-alone alarm, that should not be batched with
+ * other alarms.
+ * @hide
+ */
+ public static final int FLAG_STANDALONE = 1<<0;
+
+ /**
+ * Flag for alarms: this alarm would like to wake the device even if it is idle. This
+ * is, for example, an alarm for an alarm clock.
+ * @hide
+ */
+ public static final int FLAG_WAKE_FROM_IDLE = 1<<1;
+
+ /**
+ * Flag for alarms: this alarm would like to still execute even if the device is
+ * idle. This won't bring the device out of idle, just allow this specific alarm to
+ * run. Note that this means the actual time this alarm goes off can be inconsistent
+ * with the time of non-allow-while-idle alarms (it could go earlier than the time
+ * requested by another alarm).
+ *
+ * @hide
+ */
+ public static final int FLAG_ALLOW_WHILE_IDLE = 1<<2;
+
+ /**
+ * Flag for alarms: this alarm marks the point where we would like to come out of idle
+ * mode. It may be moved by the alarm manager to match the first wake-from-idle alarm.
+ * Scheduling an alarm with this flag puts the alarm manager in to idle mode, where it
+ * avoids scheduling any further alarms until the marker alarm is executed.
+ * @hide
+ */
+ public static final int FLAG_IDLE_UNTIL = 1<<3;
+
private final IAlarmManager mService;
private final boolean mAlwaysExact;
@@ -204,7 +238,7 @@ public class AlarmManager
* @see #RTC_WAKEUP
*/
public void set(int type, long triggerAtMillis, PendingIntent operation) {
- setImpl(type, triggerAtMillis, legacyExactLength(), 0, operation, null, null);
+ setImpl(type, triggerAtMillis, legacyExactLength(), 0, 0, operation, null, null);
}
/**
@@ -265,7 +299,8 @@ public class AlarmManager
*/
public void setRepeating(int type, long triggerAtMillis,
long intervalMillis, PendingIntent operation) {
- setImpl(type, triggerAtMillis, legacyExactLength(), intervalMillis, operation, null, null);
+ setImpl(type, triggerAtMillis, legacyExactLength(), intervalMillis, 0, operation, null,
+ null);
}
/**
@@ -315,7 +350,7 @@ public class AlarmManager
*/
public void setWindow(int type, long windowStartMillis, long windowLengthMillis,
PendingIntent operation) {
- setImpl(type, windowStartMillis, windowLengthMillis, 0, operation, null, null);
+ setImpl(type, windowStartMillis, windowLengthMillis, 0, 0, operation, null, null);
}
/**
@@ -353,7 +388,16 @@ public class AlarmManager
* @see #RTC_WAKEUP
*/
public void setExact(int type, long triggerAtMillis, PendingIntent operation) {
- setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, operation, null, null);
+ setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, 0, operation, null, null);
+ }
+
+ /**
+ * Schedule an idle-until alarm, which will keep the alarm manager idle until
+ * the given time.
+ * @hide
+ */
+ public void setIdleUntil(int type, long triggerAtMillis, PendingIntent operation) {
+ setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, FLAG_IDLE_UNTIL, operation, null, null);
}
/**
@@ -381,18 +425,19 @@ public class AlarmManager
* @see android.content.Intent#filterEquals
*/
public void setAlarmClock(AlarmClockInfo info, PendingIntent operation) {
- setImpl(RTC_WAKEUP, info.getTriggerTime(), WINDOW_EXACT, 0, operation, null, info);
+ setImpl(RTC_WAKEUP, info.getTriggerTime(), WINDOW_EXACT, 0, 0, operation, null, info);
}
/** @hide */
@SystemApi
public void set(int type, long triggerAtMillis, long windowMillis, long intervalMillis,
PendingIntent operation, WorkSource workSource) {
- setImpl(type, triggerAtMillis, windowMillis, intervalMillis, operation, workSource, null);
+ setImpl(type, triggerAtMillis, windowMillis, intervalMillis, 0, operation, workSource,
+ null);
}
private void setImpl(int type, long triggerAtMillis, long windowMillis, long intervalMillis,
- PendingIntent operation, WorkSource workSource, AlarmClockInfo alarmClock) {
+ int flags, PendingIntent operation, WorkSource workSource, AlarmClockInfo alarmClock) {
if (triggerAtMillis < 0) {
/* NOTYET
if (mAlwaysExact) {
@@ -405,7 +450,7 @@ public class AlarmManager
}
try {
- mService.set(type, triggerAtMillis, windowMillis, intervalMillis, operation,
+ mService.set(type, triggerAtMillis, windowMillis, intervalMillis, flags, operation,
workSource, alarmClock);
} catch (RemoteException ex) {
}
@@ -506,7 +551,7 @@ public class AlarmManager
*/
public void setInexactRepeating(int type, long triggerAtMillis,
long intervalMillis, PendingIntent operation) {
- setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, intervalMillis, operation, null, null);
+ setImpl(type, triggerAtMillis, WINDOW_HEURISTIC, intervalMillis, 0, operation, null, null);
}
/**
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index 3e545f9..2dbbc38 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -134,6 +134,7 @@ public class AlertDialog extends Dialog implements DialogInterface {
* {@code context}'s theme.
*
* @param context the parent context
+ * @see android.R.styleable#Theme_alertDialogTheme
*/
protected AlertDialog(Context context) {
this(context, 0);
@@ -155,6 +156,7 @@ public class AlertDialog extends Dialog implements DialogInterface {
* {@code context}'s theme.
*
* @param context the parent context
+ * @see android.R.styleable#Theme_alertDialogTheme
*/
protected AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
this(context, 0);
@@ -187,16 +189,24 @@ public class AlertDialog extends Dialog implements DialogInterface {
* @param themeResId the resource ID of the theme against which to inflate
* this dialog, or {@code 0} to use the parent
* {@code context}'s default alert dialog theme
+ * @see android.R.styleable#Theme_alertDialogTheme
*/
protected AlertDialog(Context context, @AttrRes int themeResId) {
- super(context, resolveDialogTheme(context, themeResId));
+ this(context, themeResId, true);
+ }
+
+ AlertDialog(Context context, @AttrRes int themeResId, boolean createContextThemeWrapper) {
+ super(context, createContextThemeWrapper ? resolveDialogTheme(context, themeResId) : 0,
+ createContextThemeWrapper);
mWindow.alwaysReadCloseOnTouchAttr();
mAlert = new AlertController(getContext(), this, getWindow());
}
static int resolveDialogTheme(Context context, int themeResId) {
- if (themeResId == THEME_TRADITIONAL) {
+ if (themeResId == 0) {
+ return 0;
+ } else if (themeResId == THEME_TRADITIONAL) {
return R.style.Theme_Dialog_Alert;
} else if (themeResId == THEME_HOLO_DARK) {
return R.style.Theme_Holo_Dialog_Alert;
@@ -428,7 +438,6 @@ public class AlertDialog extends Dialog implements DialogInterface {
public static class Builder {
private final AlertController.AlertParams P;
- private int mThemeResId;
/**
* Creates a builder for an alert dialog that uses the default alert
@@ -473,7 +482,6 @@ public class AlertDialog extends Dialog implements DialogInterface {
public Builder(Context context, int themeResId) {
P = new AlertController.AlertParams(new ContextThemeWrapper(
context, resolveDialogTheme(context, themeResId)));
- mThemeResId = themeResId;
}
/**
@@ -1075,7 +1083,7 @@ public class AlertDialog extends Dialog implements DialogInterface {
* create and display the dialog.
*/
public AlertDialog create() {
- final AlertDialog dialog = new AlertDialog(P.mContext, mThemeResId);
+ final AlertDialog dialog = new AlertDialog(P.mContext);
P.apply(dialog.mAlert);
dialog.setCancelable(P.mCancelable);
if (P.mCancelable) {
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 9defcbe..6a2d207 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -21,7 +21,6 @@ import android.annotation.DrawableRes;
import android.annotation.IdRes;
import android.annotation.LayoutRes;
import android.annotation.StringRes;
-import com.android.internal.app.WindowDecorActionBar;
import android.annotation.Nullable;
import android.content.ComponentName;
@@ -56,6 +55,9 @@ import android.view.Window;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
+import com.android.internal.R;
+import com.android.internal.app.WindowDecorActionBar;
+
import java.lang.ref.WeakReference;
/**
@@ -130,27 +132,32 @@ public class Dialog implements DialogInterface, Window.Callback,
};
/**
- * Create a Dialog window that uses the default dialog frame style.
- *
- * @param context The Context the Dialog is to run it. In particular, it
- * uses the window manager and theme in this context to
- * present its UI.
+ * Creates a dialog window that uses the default dialog theme.
+ * <p>
+ * The supplied {@code context} is used to obtain the window manager and
+ * base theme used to present the dialog.
+ *
+ * @param context the context in which the dialog should run
+ * @see android.R.styleable#Theme_dialogTheme
*/
public Dialog(Context context) {
this(context, 0, true);
}
/**
- * Create a Dialog window that uses a custom dialog style.
+ * Creates a dialog window that uses a custom dialog style.
+ * <p>
+ * The supplied {@code context} is used to obtain the window manager and
+ * base theme used to present the dialog.
+ * <p>
+ * The supplied {@code theme} is applied on top of the context's theme. See
+ * <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">
+ * Style and Theme Resources</a> for more information about defining and
+ * using styles.
*
- * @param context The Context in which the Dialog should run. In particular, it
- * uses the window manager and theme from this context to
- * present its UI.
- * @param theme A style resource describing the theme to use for the
- * window. See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">Style
- * and Theme Resources</a> for more information about defining and using
- * styles. This theme is applied on top of the current theme in
- * <var>context</var>. If 0, the default dialog theme will be used.
+ * @param context the context in which the dialog should run
+ * @param theme a style resource describing the theme to use for the
+ * window, or {@code 0} to use the default dialog theme
*/
public Dialog(Context context, int theme) {
this(context, theme, true);
@@ -159,9 +166,8 @@ public class Dialog implements DialogInterface, Window.Callback,
Dialog(Context context, int theme, boolean createContextThemeWrapper) {
if (createContextThemeWrapper) {
if (theme == 0) {
- TypedValue outValue = new TypedValue();
- context.getTheme().resolveAttribute(com.android.internal.R.attr.dialogTheme,
- outValue, true);
+ final TypedValue outValue = new TypedValue();
+ context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
theme = outValue.resourceId;
}
mContext = new ContextThemeWrapper(context, theme);
@@ -170,12 +176,14 @@ public class Dialog implements DialogInterface, Window.Callback,
}
mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
- Window w = new PhoneWindow(mContext);
+
+ final Window w = new PhoneWindow(mContext);
mWindow = w;
w.setCallback(this);
w.setOnWindowDismissedCallback(this);
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);
+
mListenersHandler = new ListenersHandler(this);
}
diff --git a/core/java/android/app/IAlarmManager.aidl b/core/java/android/app/IAlarmManager.aidl
index 194082e..d5719f5 100644
--- a/core/java/android/app/IAlarmManager.aidl
+++ b/core/java/android/app/IAlarmManager.aidl
@@ -28,7 +28,7 @@ import android.os.WorkSource;
interface IAlarmManager {
/** windowLength == 0 means exact; windowLength < 0 means the let the OS decide */
void set(int type, long triggerAtTime, long windowLength,
- long interval, in PendingIntent operation, in WorkSource workSource,
+ long interval, int flags, in PendingIntent operation, in WorkSource workSource,
in AlarmManager.AlarmClockInfo alarmClock);
boolean setTime(long millis);
void setTimeZone(String zone);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 33262b3..e2230da 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -76,12 +76,10 @@ interface INotificationManager
boolean matchesCallFilter(in Bundle extras);
boolean isSystemConditionProviderEnabled(String path);
+ int getZenMode();
ZenModeConfig getZenModeConfig();
- boolean setZenModeConfig(in ZenModeConfig config);
- oneway void setZenMode(int mode);
+ boolean setZenModeConfig(in ZenModeConfig config, String reason);
+ oneway void setZenMode(int mode, in Uri conditionId, String reason);
oneway void notifyConditions(String pkg, in IConditionProvider provider, in Condition[] conditions);
oneway void requestZenModeConditions(in IConditionListener callback, int relevance);
- oneway void setZenModeCondition(in Condition condition);
- oneway void setAutomaticZenModeConditions(in Uri[] conditionIds);
- Condition[] getAutomaticZenModeConditions();
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 479327d..fa61e18 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -20,6 +20,7 @@ import android.annotation.SdkConstant;
import android.app.Notification.Builder;
import android.content.ComponentName;
import android.content.Context;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -27,7 +28,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
import android.os.UserHandle;
-import android.service.notification.Condition;
+import android.provider.Settings.Global;
import android.service.notification.IConditionListener;
import android.service.notification.ZenModeConfig;
import android.util.Log;
@@ -282,10 +283,10 @@ public class NotificationManager
/**
* @hide
*/
- public void setZenMode(int mode) {
+ public void setZenMode(int mode, Uri conditionId, String reason) {
INotificationManager service = getService();
try {
- service.setZenMode(mode);
+ service.setZenMode(mode, conditionId, reason);
} catch (RemoteException e) {
}
}
@@ -293,6 +294,18 @@ public class NotificationManager
/**
* @hide
*/
+ public boolean setZenModeConfig(ZenModeConfig config, String reason) {
+ INotificationManager service = getService();
+ try {
+ return service.setZenModeConfig(config, reason);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * @hide
+ */
public void requestZenModeConditions(IConditionListener listener, int relevance) {
INotificationManager service = getService();
try {
@@ -304,24 +317,22 @@ public class NotificationManager
/**
* @hide
*/
- public void setZenModeCondition(Condition exitCondition) {
+ public int getZenMode() {
INotificationManager service = getService();
try {
- service.setZenModeCondition(exitCondition);
+ return service.getZenMode();
} catch (RemoteException e) {
}
+ return Global.ZEN_MODE_OFF;
}
/**
* @hide
*/
- public Condition getZenModeCondition() {
+ public ZenModeConfig getZenModeConfig() {
INotificationManager service = getService();
try {
- final ZenModeConfig config = service.getZenModeConfig();
- if (config != null) {
- return config.exitCondition;
- }
+ return service.getZenModeConfig();
} catch (RemoteException e) {
}
return null;
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java
index 7acf5f0..022a62c 100644
--- a/core/java/android/app/VoiceInteractor.java
+++ b/core/java/android/app/VoiceInteractor.java
@@ -318,7 +318,7 @@ public class VoiceInteractor {
* @param label The label that will both be matched against what the user speaks
* and displayed visually.
* @param index The location of this option within the overall set of options.
- * Can be used to help identify which the option when it is returned from the
+ * Can be used to help identify the option when it is returned from the
* voice interactor.
*/
public Option(CharSequence label, int index) {
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 9151a16..8b79305 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -339,4 +339,30 @@ public class BackupManager {
}
}
}
+
+ /**
+ * Ask the framework which dataset, if any, the given package's data would be
+ * restored from if we were to install it right now.
+ *
+ * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+ *
+ * @param packageName The name of the package whose most-suitable dataset we
+ * wish to look up
+ * @return The dataset token from which a restore should be attempted, or zero if
+ * no suitable data is available.
+ *
+ * @hide
+ */
+ @SystemApi
+ public long getAvailableRestoreToken(String packageName) {
+ checkServiceBinder();
+ if (sService != null) {
+ try {
+ return sService.getAvailableRestoreToken(packageName);
+ } catch (RemoteException e) {
+ Log.e(TAG, "getAvailableRestoreToken() couldn't connect");
+ }
+ }
+ return 0;
+ }
}
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index 8f36dc4..87e4ef1 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -313,4 +313,17 @@ interface IBackupManager {
* is being queried.
*/
boolean isBackupServiceActive(int whichUser);
+
+ /**
+ * Ask the framework which dataset, if any, the given package's data would be
+ * restored from if we were to install it right now.
+ *
+ * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+ *
+ * @param packageName The name of the package whose most-suitable dataset we
+ * wish to look up
+ * @return The dataset token from which a restore should be attempted, or zero if
+ * no suitable data is available.
+ */
+ long getAvailableRestoreToken(String packageName);
}
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 590d791..044e3e3 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -517,6 +517,38 @@ public class IntentFilter implements Parcelable {
}
/**
+ * Return if this filter handle all HTTP or HTTPS data URI or not.
+ *
+ * @return True if the filter handle all HTTP or HTTPS data URI. False otherwise.
+ *
+ * This will check if if the Intent action is {@link android.content.Intent#ACTION_VIEW} and
+ * the Intent category is {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent
+ * data scheme is "http" or "https" and that there is no specific host defined.
+ *
+ * @hide
+ */
+ public final boolean handleAllWebDataURI() {
+ return hasWebDataURI() && (countDataAuthorities() == 0);
+ }
+
+ /**
+ * Return if this filter has any HTTP or HTTPS data URI or not.
+ *
+ * @return True if the filter has any HTTP or HTTPS data URI. False otherwise.
+ *
+ * This will check if if the Intent action is {@link android.content.Intent#ACTION_VIEW} and
+ * the Intent category is {@link android.content.Intent#CATEGORY_BROWSABLE} and the Intent
+ * data scheme is "http" or "https".
+ *
+ * @hide
+ */
+ public final boolean hasWebDataURI() {
+ return hasAction(Intent.ACTION_VIEW) &&
+ hasCategory(Intent.CATEGORY_BROWSABLE) &&
+ (hasDataScheme(SCHEME_HTTP) || hasDataScheme(SCHEME_HTTPS));
+ }
+
+ /**
* Return if this filter needs to be automatically verified again its data URIs or not.
*
* @return True if the filter needs to be automatically verified. False otherwise.
@@ -530,10 +562,7 @@ public class IntentFilter implements Parcelable {
* @hide
*/
public final boolean needsVerification() {
- return hasAction(Intent.ACTION_VIEW) &&
- hasCategory(Intent.CATEGORY_BROWSABLE) &&
- (hasDataScheme(SCHEME_HTTP) || hasDataScheme(SCHEME_HTTPS)) &&
- getAutoVerify();
+ return hasWebDataURI() && getAutoVerify();
}
/**
diff --git a/core/java/android/content/pm/IntentFilterVerificationInfo.java b/core/java/android/content/pm/IntentFilterVerificationInfo.java
index 28cbaa8..e50b0ff 100644
--- a/core/java/android/content/pm/IntentFilterVerificationInfo.java
+++ b/core/java/android/content/pm/IntentFilterVerificationInfo.java
@@ -36,7 +36,7 @@ import java.util.ArrayList;
/**
* The {@link com.android.server.pm.PackageManagerService} maintains some
- * {@link IntentFilterVerificationInfo}s for each domain / package / class name per user.
+ * {@link IntentFilterVerificationInfo}s for each domain / package name.
*
* @hide
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index bdbed75..7523675 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2778,7 +2778,7 @@ public class PackageParser {
}
/**
- * Check if one of the IntentFilter as an action VIEW and a HTTP/HTTPS data URI
+ * Check if one of the IntentFilter as both actions DEFAULT / VIEW and a HTTP/HTTPS data URI
*/
private static boolean hasDomainURLs(Package pkg) {
if (pkg == null || pkg.activities == null) return false;
@@ -2792,8 +2792,10 @@ public class PackageParser {
for (int m=0; m<countFilters; m++) {
ActivityIntentInfo aii = filters.get(m);
if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
+ if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
+ Slog.d(TAG, "hasDomainURLs:true for package:" + pkg.packageName);
return true;
}
}
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index 7b141f0..05f5e90 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -144,9 +144,9 @@ public class ResolveInfo implements Parcelable {
public boolean system;
/**
- * @hide Does the associated IntentFilter needs verification ?
+ * @hide Does the associated IntentFilter comes from a Browser ?
*/
- public boolean filterNeedsVerification;
+ public boolean handleAllWebDataURI;
private ComponentInfo getComponentInfo() {
if (activityInfo != null) return activityInfo;
@@ -288,7 +288,7 @@ public class ResolveInfo implements Parcelable {
resolvePackageName = orig.resolvePackageName;
system = orig.system;
targetUserId = orig.targetUserId;
- filterNeedsVerification = orig.filterNeedsVerification;
+ handleAllWebDataURI = orig.handleAllWebDataURI;
}
public String toString() {
@@ -350,7 +350,7 @@ public class ResolveInfo implements Parcelable {
dest.writeInt(targetUserId);
dest.writeInt(system ? 1 : 0);
dest.writeInt(noResourceId ? 1 : 0);
- dest.writeInt(filterNeedsVerification ? 1 : 0);
+ dest.writeInt(handleAllWebDataURI ? 1 : 0);
}
public static final Creator<ResolveInfo> CREATOR
@@ -396,7 +396,7 @@ public class ResolveInfo implements Parcelable {
targetUserId = source.readInt();
system = source.readInt() != 0;
noResourceId = source.readInt() != 0;
- filterNeedsVerification = source.readInt() != 0;
+ handleAllWebDataURI = source.readInt() != 0;
}
public static class DisplayNameComparator
diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java
index b5b89dd..581fe7f 100644
--- a/core/java/android/database/AbstractCursor.java
+++ b/core/java/android/database/AbstractCursor.java
@@ -35,34 +35,38 @@ public abstract class AbstractCursor implements CrossProcessCursor {
private static final String TAG = "Cursor";
/**
- * @deprecated This is never updated by this class and should not be used
+ * @removed This field should not be used.
*/
- @Deprecated
protected HashMap<Long, Map<String, Object>> mUpdatedRows;
- protected int mPos;
-
/**
- * This must be set to the index of the row ID column by any
- * subclass that wishes to support updates.
- *
- * @deprecated This field should not be used.
+ * @removed This field should not be used.
*/
- @Deprecated
protected int mRowIdColumnIndex;
/**
- * If {@link #mRowIdColumnIndex} is not -1 this contains contains the value of
- * the column at {@link #mRowIdColumnIndex} for the current row this cursor is
- * pointing at.
- *
- * @deprecated This field should not be used.
+ * @removed This field should not be used.
*/
- @Deprecated
protected Long mCurrentRowID;
+ /**
+ * @deprecated Use {@link #getPosition()} instead.
+ */
+ @Deprecated
+ protected int mPos;
+
+ /**
+ * @deprecated Use {@link #isClosed()} instead.
+ */
+ @Deprecated
protected boolean mClosed;
+
+ /**
+ * @deprecated Do not use.
+ */
+ @Deprecated
protected ContentResolver mContentResolver;
+
private Uri mNotifyUri;
private final Object mSelfObserverLock = new Object();
@@ -76,18 +80,28 @@ public abstract class AbstractCursor implements CrossProcessCursor {
/* -------------------------------------------------------- */
/* These need to be implemented by subclasses */
+ @Override
abstract public int getCount();
+ @Override
abstract public String[] getColumnNames();
+ @Override
abstract public String getString(int column);
+ @Override
abstract public short getShort(int column);
+ @Override
abstract public int getInt(int column);
+ @Override
abstract public long getLong(int column);
+ @Override
abstract public float getFloat(int column);
+ @Override
abstract public double getDouble(int column);
+ @Override
abstract public boolean isNull(int column);
+ @Override
public int getType(int column) {
// Reflects the assumption that all commonly used field types (meaning everything
// but blobs) are convertible to strings so it should be safe to call
@@ -96,6 +110,7 @@ public abstract class AbstractCursor implements CrossProcessCursor {
}
// TODO implement getBlob in all cursor types
+ @Override
public byte[] getBlob(int column) {
throw new UnsupportedOperationException("getBlob is not supported");
}
@@ -108,14 +123,17 @@ public abstract class AbstractCursor implements CrossProcessCursor {
*
* @return The pre-filled window that backs this cursor, or null if none.
*/
+ @Override
public CursorWindow getWindow() {
return null;
}
+ @Override
public int getColumnCount() {
return getColumnNames().length;
}
+ @Override
public void deactivate() {
onDeactivateOrClose();
}
@@ -129,6 +147,7 @@ public abstract class AbstractCursor implements CrossProcessCursor {
mDataSetObservable.notifyInvalidated();
}
+ @Override
public boolean requery() {
if (mSelfObserver != null && mSelfObserverRegistered == false) {
mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);
@@ -138,10 +157,12 @@ public abstract class AbstractCursor implements CrossProcessCursor {
return true;
}
+ @Override
public boolean isClosed() {
return mClosed;
}
+ @Override
public void close() {
mClosed = true;
mContentObservable.unregisterAll();
@@ -158,11 +179,13 @@ public abstract class AbstractCursor implements CrossProcessCursor {
* @param newPosition the position that we're moving to
* @return true if the move is successful, false otherwise
*/
+ @Override
public boolean onMove(int oldPosition, int newPosition) {
return true;
}
+ @Override
public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
// Default implementation, uses getString
String result = getString(columnIndex);
@@ -183,15 +206,14 @@ public abstract class AbstractCursor implements CrossProcessCursor {
/* Implementation */
public AbstractCursor() {
mPos = -1;
- mRowIdColumnIndex = -1;
- mCurrentRowID = null;
- mUpdatedRows = new HashMap<Long, Map<String, Object>>();
}
+ @Override
public final int getPosition() {
return mPos;
}
+ @Override
public final boolean moveToPosition(int position) {
// Make sure position isn't past the end of the cursor
final int count = getCount();
@@ -216,9 +238,6 @@ public abstract class AbstractCursor implements CrossProcessCursor {
mPos = -1;
} else {
mPos = position;
- if (mRowIdColumnIndex != -1) {
- mCurrentRowID = Long.valueOf(getLong(mRowIdColumnIndex));
- }
}
return result;
@@ -229,35 +248,43 @@ public abstract class AbstractCursor implements CrossProcessCursor {
DatabaseUtils.cursorFillWindow(this, position, window);
}
+ @Override
public final boolean move(int offset) {
return moveToPosition(mPos + offset);
}
+ @Override
public final boolean moveToFirst() {
return moveToPosition(0);
}
+ @Override
public final boolean moveToLast() {
return moveToPosition(getCount() - 1);
}
+ @Override
public final boolean moveToNext() {
return moveToPosition(mPos + 1);
}
+ @Override
public final boolean moveToPrevious() {
return moveToPosition(mPos - 1);
}
+ @Override
public final boolean isFirst() {
return mPos == 0 && getCount() != 0;
}
+ @Override
public final boolean isLast() {
int cnt = getCount();
return mPos == (cnt - 1) && cnt != 0;
}
+ @Override
public final boolean isBeforeFirst() {
if (getCount() == 0) {
return true;
@@ -265,6 +292,7 @@ public abstract class AbstractCursor implements CrossProcessCursor {
return mPos == -1;
}
+ @Override
public final boolean isAfterLast() {
if (getCount() == 0) {
return true;
@@ -272,6 +300,7 @@ public abstract class AbstractCursor implements CrossProcessCursor {
return mPos == getCount();
}
+ @Override
public int getColumnIndex(String columnName) {
// Hack according to bug 903852
final int periodIndex = columnName.lastIndexOf('.');
@@ -297,6 +326,7 @@ public abstract class AbstractCursor implements CrossProcessCursor {
return -1;
}
+ @Override
public int getColumnIndexOrThrow(String columnName) {
final int index = getColumnIndex(columnName);
if (index < 0) {
@@ -305,14 +335,17 @@ public abstract class AbstractCursor implements CrossProcessCursor {
return index;
}
+ @Override
public String getColumnName(int columnIndex) {
return getColumnNames()[columnIndex];
}
+ @Override
public void registerContentObserver(ContentObserver observer) {
mContentObservable.registerObserver(observer);
}
+ @Override
public void unregisterContentObserver(ContentObserver observer) {
// cursor will unregister all observers when it close
if (!mClosed) {
@@ -320,10 +353,12 @@ public abstract class AbstractCursor implements CrossProcessCursor {
}
}
+ @Override
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
+ @Override
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
@@ -350,6 +385,7 @@ public abstract class AbstractCursor implements CrossProcessCursor {
* @param notifyUri The URI to watch for changes. This can be a
* specific row URI, or a base URI for a whole class of content.
*/
+ @Override
public void setNotificationUri(ContentResolver cr, Uri notifyUri) {
setNotificationUri(cr, notifyUri, UserHandle.myUserId());
}
@@ -368,31 +404,29 @@ public abstract class AbstractCursor implements CrossProcessCursor {
}
}
+ @Override
public Uri getNotificationUri() {
synchronized (mSelfObserverLock) {
return mNotifyUri;
}
}
+ @Override
public boolean getWantsAllOnMoveCalls() {
return false;
}
- /**
- * Sets a {@link Bundle} that will be returned by {@link #getExtras()}. <code>null</code> will
- * be converted into {@link Bundle#EMPTY}.
- *
- * @param extras {@link Bundle} to set.
- * @hide
- */
+ @Override
public void setExtras(Bundle extras) {
mExtras = (extras == null) ? Bundle.EMPTY : extras;
}
+ @Override
public Bundle getExtras() {
return mExtras;
}
+ @Override
public Bundle respond(Bundle extras) {
return Bundle.EMPTY;
}
diff --git a/core/java/android/database/BulkCursorToCursorAdaptor.java b/core/java/android/database/BulkCursorToCursorAdaptor.java
index 98c7043..8576715 100644
--- a/core/java/android/database/BulkCursorToCursorAdaptor.java
+++ b/core/java/android/database/BulkCursorToCursorAdaptor.java
@@ -41,7 +41,6 @@ public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor {
public void initialize(BulkCursorDescriptor d) {
mBulkCursor = d.cursor;
mColumns = d.columnNames;
- mRowIdColumnIndex = DatabaseUtils.findRowIdColumnIndex(mColumns);
mWantsAllOnMoveCalls = d.wantsAllOnMoveCalls;
mCount = d.count;
if (d.window != null) {
diff --git a/core/java/android/database/Cursor.java b/core/java/android/database/Cursor.java
index fc2a885..d10c9b8 100644
--- a/core/java/android/database/Cursor.java
+++ b/core/java/android/database/Cursor.java
@@ -444,6 +444,13 @@ public interface Cursor extends Closeable {
boolean getWantsAllOnMoveCalls();
/**
+ * Sets a {@link Bundle} that will be returned by {@link #getExtras()}.
+ *
+ * @param extras {@link Bundle} to set, or null to set an empty bundle.
+ */
+ void setExtras(Bundle extras);
+
+ /**
* Returns a bundle of extra values. This is an optional way for cursors to provide out-of-band
* metadata to their users. One use of this is for reporting on the progress of network requests
* that are required to fetch data for the cursor.
diff --git a/core/java/android/database/CursorWrapper.java b/core/java/android/database/CursorWrapper.java
index d8fcb17..63a2792 100644
--- a/core/java/android/database/CursorWrapper.java
+++ b/core/java/android/database/CursorWrapper.java
@@ -45,163 +45,210 @@ public class CursorWrapper implements Cursor {
return mCursor;
}
+ @Override
public void close() {
mCursor.close();
}
+ @Override
public boolean isClosed() {
return mCursor.isClosed();
}
+ @Override
public int getCount() {
return mCursor.getCount();
}
+ @Override
+ @Deprecated
public void deactivate() {
mCursor.deactivate();
}
+ @Override
public boolean moveToFirst() {
return mCursor.moveToFirst();
}
+ @Override
public int getColumnCount() {
return mCursor.getColumnCount();
}
+ @Override
public int getColumnIndex(String columnName) {
return mCursor.getColumnIndex(columnName);
}
+ @Override
public int getColumnIndexOrThrow(String columnName)
throws IllegalArgumentException {
return mCursor.getColumnIndexOrThrow(columnName);
}
+ @Override
public String getColumnName(int columnIndex) {
return mCursor.getColumnName(columnIndex);
}
+ @Override
public String[] getColumnNames() {
return mCursor.getColumnNames();
}
+ @Override
public double getDouble(int columnIndex) {
return mCursor.getDouble(columnIndex);
}
+ @Override
+ public void setExtras(Bundle extras) {
+ mCursor.setExtras(extras);
+ }
+
+ @Override
public Bundle getExtras() {
return mCursor.getExtras();
}
+ @Override
public float getFloat(int columnIndex) {
return mCursor.getFloat(columnIndex);
}
+ @Override
public int getInt(int columnIndex) {
return mCursor.getInt(columnIndex);
}
+ @Override
public long getLong(int columnIndex) {
return mCursor.getLong(columnIndex);
}
+ @Override
public short getShort(int columnIndex) {
return mCursor.getShort(columnIndex);
}
+ @Override
public String getString(int columnIndex) {
return mCursor.getString(columnIndex);
}
+ @Override
public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
mCursor.copyStringToBuffer(columnIndex, buffer);
}
+ @Override
public byte[] getBlob(int columnIndex) {
return mCursor.getBlob(columnIndex);
}
+ @Override
public boolean getWantsAllOnMoveCalls() {
return mCursor.getWantsAllOnMoveCalls();
}
+ @Override
public boolean isAfterLast() {
return mCursor.isAfterLast();
}
+ @Override
public boolean isBeforeFirst() {
return mCursor.isBeforeFirst();
}
+ @Override
public boolean isFirst() {
return mCursor.isFirst();
}
+ @Override
public boolean isLast() {
return mCursor.isLast();
}
+ @Override
public int getType(int columnIndex) {
return mCursor.getType(columnIndex);
}
+ @Override
public boolean isNull(int columnIndex) {
return mCursor.isNull(columnIndex);
}
+ @Override
public boolean moveToLast() {
return mCursor.moveToLast();
}
+ @Override
public boolean move(int offset) {
return mCursor.move(offset);
}
+ @Override
public boolean moveToPosition(int position) {
return mCursor.moveToPosition(position);
}
+ @Override
public boolean moveToNext() {
return mCursor.moveToNext();
}
+ @Override
public int getPosition() {
return mCursor.getPosition();
}
+ @Override
public boolean moveToPrevious() {
return mCursor.moveToPrevious();
}
+ @Override
public void registerContentObserver(ContentObserver observer) {
- mCursor.registerContentObserver(observer);
+ mCursor.registerContentObserver(observer);
}
+ @Override
public void registerDataSetObserver(DataSetObserver observer) {
- mCursor.registerDataSetObserver(observer);
+ mCursor.registerDataSetObserver(observer);
}
+ @Override
+ @Deprecated
public boolean requery() {
return mCursor.requery();
}
+ @Override
public Bundle respond(Bundle extras) {
return mCursor.respond(extras);
}
+ @Override
public void setNotificationUri(ContentResolver cr, Uri uri) {
- mCursor.setNotificationUri(cr, uri);
+ mCursor.setNotificationUri(cr, uri);
}
+ @Override
public Uri getNotificationUri() {
return mCursor.getNotificationUri();
}
+ @Override
public void unregisterContentObserver(ContentObserver observer) {
- mCursor.unregisterContentObserver(observer);
+ mCursor.unregisterContentObserver(observer);
}
+ @Override
public void unregisterDataSetObserver(DataSetObserver observer) {
mCursor.unregisterDataSetObserver(observer);
}
diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java
index 5a1a8e2..2dc5ca4 100644
--- a/core/java/android/database/sqlite/SQLiteCursor.java
+++ b/core/java/android/database/sqlite/SQLiteCursor.java
@@ -105,7 +105,6 @@ public class SQLiteCursor extends AbstractWindowedCursor {
mQuery = query;
mColumns = query.getColumnNames();
- mRowIdColumnIndex = DatabaseUtils.findRowIdColumnIndex(mColumns);
}
/**
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index bd5a392..cccc4be 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -16,10 +16,12 @@
package android.os;
+import android.content.Context;
import android.os.BatteryProperty;
import android.os.IBatteryPropertiesRegistrar;
import android.os.RemoteException;
import android.os.ServiceManager;
+import com.android.internal.app.IBatteryStats;
/**
* The BatteryManager class contains strings and constants used for values
@@ -128,6 +130,26 @@ public class BatteryManager {
public static final int BATTERY_PLUGGED_ANY =
BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS;
+ /**
+ * Sent when the device's battery has started charging (or has reached full charge
+ * and the device is on power). This is a good time to do work that you would like to
+ * avoid doing while on battery (that is to avoid draining the user's battery due to
+ * things they don't care enough about).
+ *
+ * This is paired with {@link #ACTION_DISCHARGING}. The current state can always
+ * be retrieved with {@link #isCharging()}.
+ */
+ public static final String ACTION_CHARGING = "android.os.action.CHARGING";
+
+ /**
+ * Sent when the device's battery may be discharging, so apps should avoid doing
+ * extraneous work that would cause it to discharge faster.
+ *
+ * This is paired with {@link #ACTION_CHARGING}. The current state can always
+ * be retrieved with {@link #isCharging()}.
+ */
+ public static final String ACTION_DISCHARGING = "android.os.action.DISCHARGING";
+
/*
* Battery property identifiers. These must match the values in
* frameworks/native/include/batteryservice/BatteryService.h
@@ -162,17 +184,34 @@ public class BatteryManager {
*/
public static final int BATTERY_PROPERTY_ENERGY_COUNTER = 5;
+ private final IBatteryStats mBatteryStats;
private final IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
/**
* @removed Was previously made visible by accident.
*/
public BatteryManager() {
+ mBatteryStats = IBatteryStats.Stub.asInterface(
+ ServiceManager.getService(BatteryStats.SERVICE_NAME));
mBatteryPropertiesRegistrar = IBatteryPropertiesRegistrar.Stub.asInterface(
ServiceManager.getService("batteryproperties"));
}
/**
+ * Return true if the battery is currently considered to be charging. This means that
+ * the device is plugged in and is supplying sufficient power that the battery level is
+ * going up (or the battery is fully charged). Changes in this state are matched by
+ * broadcasts of {@link #ACTION_CHARGING} and {@link #ACTION_DISCHARGING}.
+ */
+ public boolean isCharging() {
+ try {
+ return mBatteryStats.isCharging();
+ } catch (RemoteException e) {
+ return true;
+ }
+ }
+
+ /**
* Query a battery property from the batteryproperties service.
*
* Returns the requested value, or Long.MIN_VALUE if property not
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 3051926..1566985 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1065,6 +1065,7 @@ public abstract class BatteryStats implements Parcelable {
public static final int STATE_SCREEN_ON_FLAG = 1<<20;
public static final int STATE_BATTERY_PLUGGED_FLAG = 1<<19;
public static final int STATE_PHONE_IN_CALL_FLAG = 1<<18;
+ public static final int STATE_CHARGING_FLAG = 1<<17;
public static final int STATE_BLUETOOTH_ON_FLAG = 1<<16;
public static final int MOST_INTERESTING_STATES =
@@ -1751,6 +1752,7 @@ public abstract class BatteryStats implements Parcelable {
new BitDescription(HistoryItem.STATE_SCREEN_ON_FLAG, "screen", "S"),
new BitDescription(HistoryItem.STATE_BATTERY_PLUGGED_FLAG, "plugged", "BP"),
new BitDescription(HistoryItem.STATE_PHONE_IN_CALL_FLAG, "phone_in_call", "Pcl"),
+ new BitDescription(HistoryItem.STATE_CHARGING_FLAG, "charging", "ch"),
new BitDescription(HistoryItem.STATE_BLUETOOTH_ON_FLAG, "bluetooth", "b"),
new BitDescription(HistoryItem.STATE_DATA_CONNECTION_MASK,
HistoryItem.STATE_DATA_CONNECTION_SHIFT, "data_conn", "Pcn",
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5ee8fb3..3087e1d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -880,6 +880,15 @@ public final class Settings {
"android.settings.VOICE_CONTROL_DO_NOT_DISTURB_MODE";
/**
+ * Activity Action: Show Zen Mode schedule rule configuration settings.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_ZEN_MODE_SCHEDULE_RULE_SETTINGS
+ = "android.settings.ZEN_MODE_SCHEDULE_RULE_SETTINGS";
+
+ /**
* Activity Action: Show the regulatory information screen for the device.
* <p>
* In some cases, a matching Activity may not exist, so ensure you safeguard
@@ -7218,6 +7227,18 @@ public final class Settings {
return "ZEN_MODE_OFF";
}
+ /** @hide */ public static boolean isValidZenMode(int value) {
+ switch (value) {
+ case Global.ZEN_MODE_OFF:
+ case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
+ case Global.ZEN_MODE_ALARMS:
+ case Global.ZEN_MODE_NO_INTERRUPTIONS:
+ return true;
+ default:
+ return false;
+ }
+ }
+
/**
* Opaque value, changes when persisted zen mode configuration changes.
*
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 5e2accd..dc5770b 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -59,9 +59,6 @@ public final class KeymasterDefs {
public static final int KM_TAG_BLOB_USAGE_REQUIREMENTS = KM_ENUM | 705;
public static final int KM_TAG_RSA_PUBLIC_EXPONENT = KM_LONG | 200;
- public static final int KM_TAG_DSA_GENERATOR = KM_BIGNUM | 201;
- public static final int KM_TAG_DSA_P = KM_BIGNUM | 202;
- public static final int KM_TAG_DSA_Q = KM_BIGNUM | 203;
public static final int KM_TAG_ACTIVE_DATETIME = KM_DATE | 400;
public static final int KM_TAG_ORIGINATION_EXPIRE_DATETIME = KM_DATE | 401;
public static final int KM_TAG_USAGE_EXPIRE_DATETIME = KM_DATE | 402;
@@ -91,22 +88,8 @@ public final class KeymasterDefs {
// Algorithm values.
public static final int KM_ALGORITHM_RSA = 1;
- public static final int KM_ALGORITHM_DSA = 2;
- public static final int KM_ALGORITHM_ECDSA = 3;
- public static final int KM_ALGORITHM_ECIES = 4;
+ public static final int KM_ALGORITHM_EC = 3;
public static final int KM_ALGORITHM_AES = 32;
- public static final int KM_ALGORITHM_3DES = 33;
- public static final int KM_ALGORITHM_SKIPJACK = 34;
- public static final int KM_ALGORITHM_MARS = 48;
- public static final int KM_ALGORITHM_RC6 = 49;
- public static final int KM_ALGORITHM_SERPENT = 50;
- public static final int KM_ALGORITHM_TWOFISH = 51;
- public static final int KM_ALGORITHM_IDEA = 52;
- public static final int KM_ALGORITHM_RC5 = 53;
- public static final int KM_ALGORITHM_CAST5 = 54;
- public static final int KM_ALGORITHM_BLOWFISH = 55;
- public static final int KM_ALGORITHM_RC4 = 64;
- public static final int KM_ALGORITHM_CHACHA20 = 65;
public static final int KM_ALGORITHM_HMAC = 128;
// Block modes.
@@ -219,7 +202,6 @@ public final class KeymasterDefs {
public static final int KM_ERROR_INVALID_TAG = -40;
public static final int KM_ERROR_MEMORY_ALLOCATION_FAILED = -41;
public static final int KM_ERROR_INVALID_RESCOPING = -42;
- public static final int KM_ERROR_INVALID_DSA_PARAMS = -43;
public static final int KM_ERROR_IMPORT_PARAMETER_MISMATCH = -44;
public static final int KM_ERROR_SECURE_HW_ACCESS_DENIED = -45;
public static final int KM_ERROR_OPERATION_CANCELLED = -46;
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 2702457..5aaf2e7 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -22,22 +22,25 @@ import android.content.res.Resources;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
+import android.provider.Settings.Global;
import android.text.TextUtils;
import android.text.format.DateFormat;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Slog;
+import com.android.internal.R;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Calendar;
import java.util.Locale;
import java.util.Objects;
-
-import com.android.internal.R;
+import java.util.UUID;
/**
* Persisted configuration for zen mode.
@@ -47,10 +50,6 @@ import com.android.internal.R;
public class ZenModeConfig implements Parcelable {
private static String TAG = "ZenModeConfig";
- public static final String SLEEP_MODE_NIGHTS = "nights";
- public static final String SLEEP_MODE_WEEKNIGHTS = "weeknights";
- public static final String SLEEP_MODE_DAYS_PREFIX = "days:";
-
public static final int SOURCE_ANYONE = 0;
public static final int SOURCE_CONTACT = 1;
public static final int SOURCE_STAR = 2;
@@ -60,6 +59,7 @@ public class ZenModeConfig implements Parcelable {
Calendar.WEDNESDAY, Calendar.THURSDAY, Calendar.FRIDAY, Calendar.SATURDAY };
public static final int[] WEEKNIGHT_DAYS = { Calendar.SUNDAY, Calendar.MONDAY, Calendar.TUESDAY,
Calendar.WEDNESDAY, Calendar.THURSDAY };
+ public static final int[] WEEKEND_DAYS = { Calendar.FRIDAY, Calendar.SATURDAY };
public static final int[] MINUTE_BUCKETS = new int[] { 15, 30, 45, 60, 120, 180, 240, 480 };
private static final int SECONDS_MS = 1000;
@@ -69,7 +69,7 @@ public class ZenModeConfig implements Parcelable {
private static final boolean DEFAULT_ALLOW_REMINDERS = true;
private static final boolean DEFAULT_ALLOW_EVENTS = true;
- private static final int XML_VERSION = 1;
+ private static final int XML_VERSION = 2;
private static final String ZEN_TAG = "zen";
private static final String ZEN_ATT_VERSION = "version";
private static final String ALLOW_TAG = "allow";
@@ -78,14 +78,6 @@ public class ZenModeConfig implements Parcelable {
private static final String ALLOW_ATT_FROM = "from";
private static final String ALLOW_ATT_REMINDERS = "reminders";
private static final String ALLOW_ATT_EVENTS = "events";
- private static final String SLEEP_TAG = "sleep";
- private static final String SLEEP_ATT_MODE = "mode";
- private static final String SLEEP_ATT_NONE = "none";
-
- private static final String SLEEP_ATT_START_HR = "startHour";
- private static final String SLEEP_ATT_START_MIN = "startMin";
- private static final String SLEEP_ATT_END_HR = "endHour";
- private static final String SLEEP_ATT_END_MIN = "endMin";
private static final String CONDITION_TAG = "condition";
private static final String CONDITION_ATT_COMPONENT = "component";
@@ -97,8 +89,16 @@ public class ZenModeConfig implements Parcelable {
private static final String CONDITION_ATT_STATE = "state";
private static final String CONDITION_ATT_FLAGS = "flags";
- private static final String EXIT_CONDITION_TAG = "exitCondition";
- private static final String EXIT_CONDITION_ATT_COMPONENT = "component";
+ private static final String MANUAL_TAG = "manual";
+ private static final String AUTOMATIC_TAG = "automatic";
+
+ private static final String RULE_ATT_ID = "id";
+ private static final String RULE_ATT_ENABLED = "enabled";
+ private static final String RULE_ATT_SNOOZING = "snoozing";
+ private static final String RULE_ATT_NAME = "name";
+ private static final String RULE_ATT_COMPONENT = "component";
+ private static final String RULE_ATT_ZEN = "zen";
+ private static final String RULE_ATT_CONDITION_ID = "conditionId";
public boolean allowCalls;
public boolean allowMessages;
@@ -106,16 +106,8 @@ public class ZenModeConfig implements Parcelable {
public boolean allowEvents = DEFAULT_ALLOW_EVENTS;
public int allowFrom = SOURCE_ANYONE;
- public String sleepMode;
- public int sleepStartHour; // 0-23
- public int sleepStartMinute; // 0-59
- public int sleepEndHour;
- public int sleepEndMinute;
- public boolean sleepNone; // false = priority, true = none
- public ComponentName[] conditionComponents;
- public Uri[] conditionIds;
- public Condition exitCondition;
- public ComponentName exitConditionComponent;
+ public ZenRule manualRule;
+ public ArrayMap<String, ZenRule> automaticRules = new ArrayMap<>();
public ZenModeConfig() { }
@@ -124,27 +116,18 @@ public class ZenModeConfig implements Parcelable {
allowMessages = source.readInt() == 1;
allowReminders = source.readInt() == 1;
allowEvents = source.readInt() == 1;
- if (source.readInt() == 1) {
- sleepMode = source.readString();
- }
- sleepStartHour = source.readInt();
- sleepStartMinute = source.readInt();
- sleepEndHour = source.readInt();
- sleepEndMinute = source.readInt();
- sleepNone = source.readInt() == 1;
- int len = source.readInt();
- if (len > 0) {
- conditionComponents = new ComponentName[len];
- source.readTypedArray(conditionComponents, ComponentName.CREATOR);
- }
- len = source.readInt();
+ allowFrom = source.readInt();
+ manualRule = source.readParcelable(null);
+ final int len = source.readInt();
if (len > 0) {
- conditionIds = new Uri[len];
- source.readTypedArray(conditionIds, Uri.CREATOR);
+ final String[] ids = new String[len];
+ final ZenRule[] rules = new ZenRule[len];
+ source.readStringArray(ids);
+ source.readTypedArray(rules, ZenRule.CREATOR);
+ for (int i = 0; i < len; i++) {
+ automaticRules.put(ids[i], rules[i]);
+ }
}
- allowFrom = source.readInt();
- exitCondition = source.readParcelable(null);
- exitConditionComponent = source.readParcelable(null);
}
@Override
@@ -153,32 +136,22 @@ public class ZenModeConfig implements Parcelable {
dest.writeInt(allowMessages ? 1 : 0);
dest.writeInt(allowReminders ? 1 : 0);
dest.writeInt(allowEvents ? 1 : 0);
- if (sleepMode != null) {
- dest.writeInt(1);
- dest.writeString(sleepMode);
- } else {
- dest.writeInt(0);
- }
- dest.writeInt(sleepStartHour);
- dest.writeInt(sleepStartMinute);
- dest.writeInt(sleepEndHour);
- dest.writeInt(sleepEndMinute);
- dest.writeInt(sleepNone ? 1 : 0);
- if (conditionComponents != null && conditionComponents.length > 0) {
- dest.writeInt(conditionComponents.length);
- dest.writeTypedArray(conditionComponents, 0);
- } else {
- dest.writeInt(0);
- }
- if (conditionIds != null && conditionIds.length > 0) {
- dest.writeInt(conditionIds.length);
- dest.writeTypedArray(conditionIds, 0);
+ dest.writeInt(allowFrom);
+ dest.writeParcelable(manualRule, 0);
+ if (!automaticRules.isEmpty()) {
+ final int len = automaticRules.size();
+ final String[] ids = new String[len];
+ final ZenRule[] rules = new ZenRule[len];
+ for (int i = 0; i < len; i++) {
+ ids[i] = automaticRules.keyAt(i);
+ rules[i] = automaticRules.valueAt(i);
+ }
+ dest.writeInt(len);
+ dest.writeStringArray(ids);
+ dest.writeTypedArray(rules, 0);
} else {
dest.writeInt(0);
}
- dest.writeInt(allowFrom);
- dest.writeParcelable(exitCondition, 0);
- dest.writeParcelable(exitConditionComponent, 0);
}
@Override
@@ -189,19 +162,38 @@ public class ZenModeConfig implements Parcelable {
.append(",allowFrom=").append(sourceToString(allowFrom))
.append(",allowReminders=").append(allowReminders)
.append(",allowEvents=").append(allowEvents)
- .append(",sleepMode=").append(sleepMode)
- .append(",sleepStart=").append(sleepStartHour).append('.').append(sleepStartMinute)
- .append(",sleepEnd=").append(sleepEndHour).append('.').append(sleepEndMinute)
- .append(",sleepNone=").append(sleepNone)
- .append(",conditionComponents=")
- .append(conditionComponents == null ? null : TextUtils.join(",", conditionComponents))
- .append(",conditionIds=")
- .append(conditionIds == null ? null : TextUtils.join(",", conditionIds))
- .append(",exitCondition=").append(exitCondition)
- .append(",exitConditionComponent=").append(exitConditionComponent)
+ .append(",automaticRules=").append(automaticRules)
+ .append(",manualRule=").append(manualRule)
.append(']').toString();
}
+ public boolean isValid() {
+ if (!isValidManualRule(manualRule)) return false;
+ final int N = automaticRules.size();
+ for (int i = 0; i < N; i++) {
+ if (!isValidAutomaticRule(automaticRules.valueAt(i))) return false;
+ }
+ return true;
+ }
+
+ private static boolean isValidManualRule(ZenRule rule) {
+ return rule == null || Global.isValidZenMode(rule.zenMode) && sameCondition(rule);
+ }
+
+ private static boolean isValidAutomaticRule(ZenRule rule) {
+ return rule != null && !TextUtils.isEmpty(rule.name) && Global.isValidZenMode(rule.zenMode)
+ && rule.conditionId != null && sameCondition(rule);
+ }
+
+ private static boolean sameCondition(ZenRule rule) {
+ if (rule == null) return false;
+ if (rule.conditionId == null) {
+ return rule.condition == null;
+ } else {
+ return rule.condition == null || rule.conditionId.equals(rule.condition.id);
+ }
+ }
+
public static String sourceToString(int source) {
switch (source) {
case SOURCE_ANYONE:
@@ -225,45 +217,29 @@ public class ZenModeConfig implements Parcelable {
&& other.allowFrom == allowFrom
&& other.allowReminders == allowReminders
&& other.allowEvents == allowEvents
- && Objects.equals(other.sleepMode, sleepMode)
- && other.sleepNone == sleepNone
- && other.sleepStartHour == sleepStartHour
- && other.sleepStartMinute == sleepStartMinute
- && other.sleepEndHour == sleepEndHour
- && other.sleepEndMinute == sleepEndMinute
- && Objects.deepEquals(other.conditionComponents, conditionComponents)
- && Objects.deepEquals(other.conditionIds, conditionIds)
- && Objects.equals(other.exitCondition, exitCondition)
- && Objects.equals(other.exitConditionComponent, exitConditionComponent);
+ && Objects.equals(other.automaticRules, automaticRules)
+ && Objects.equals(other.manualRule, manualRule);
}
@Override
public int hashCode() {
return Objects.hash(allowCalls, allowMessages, allowFrom, allowReminders, allowEvents,
- sleepMode, sleepNone, sleepStartHour, sleepStartMinute, sleepEndHour,
- sleepEndMinute, Arrays.hashCode(conditionComponents), Arrays.hashCode(conditionIds),
- exitCondition, exitConditionComponent);
+ automaticRules, manualRule);
}
- public boolean isValid() {
- return isValidHour(sleepStartHour) && isValidMinute(sleepStartMinute)
- && isValidHour(sleepEndHour) && isValidMinute(sleepEndMinute)
- && isValidSleepMode(sleepMode);
- }
-
- public static boolean isValidSleepMode(String sleepMode) {
- return sleepMode == null || sleepMode.equals(SLEEP_MODE_NIGHTS)
- || sleepMode.equals(SLEEP_MODE_WEEKNIGHTS) || tryParseDays(sleepMode) != null;
+ private static String toDayList(int[] days) {
+ if (days == null || days.length == 0) return "";
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < days.length; i++) {
+ if (i > 0) sb.append('.');
+ sb.append(days[i]);
+ }
+ return sb.toString();
}
- public static int[] tryParseDays(String sleepMode) {
- if (sleepMode == null) return null;
- sleepMode = sleepMode.trim();
- if (SLEEP_MODE_NIGHTS.equals(sleepMode)) return ALL_DAYS;
- if (SLEEP_MODE_WEEKNIGHTS.equals(sleepMode)) return WEEKNIGHT_DAYS;
- if (!sleepMode.startsWith(SLEEP_MODE_DAYS_PREFIX)) return null;
- if (sleepMode.equals(SLEEP_MODE_DAYS_PREFIX)) return null;
- final String[] tokens = sleepMode.substring(SLEEP_MODE_DAYS_PREFIX.length()).split(",");
+ private static int[] tryParseDayList(String dayList, String sep) {
+ if (dayList == null) return null;
+ final String[] tokens = dayList.split(sep);
if (tokens.length == 0) return null;
final int[] rt = new int[tokens.length];
for (int i = 0; i < tokens.length; i++) {
@@ -283,7 +259,7 @@ public class ZenModeConfig implements Parcelable {
}
}
- public static ZenModeConfig readXml(XmlPullParser parser)
+ public static ZenModeConfig readXml(XmlPullParser parser, Migration migration)
throws XmlPullParserException, IOException {
int type = parser.getEventType();
if (type != XmlPullParser.START_TAG) return null;
@@ -291,16 +267,13 @@ public class ZenModeConfig implements Parcelable {
if (!ZEN_TAG.equals(tag)) return null;
final ZenModeConfig rt = new ZenModeConfig();
final int version = safeInt(parser, ZEN_ATT_VERSION, XML_VERSION);
- final ArrayList<ComponentName> conditionComponents = new ArrayList<ComponentName>();
- final ArrayList<Uri> conditionIds = new ArrayList<Uri>();
+ if (version == 1) {
+ final XmlV1 v1 = XmlV1.readXml(parser);
+ return migration.migrate(v1);
+ }
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
tag = parser.getName();
if (type == XmlPullParser.END_TAG && ZEN_TAG.equals(tag)) {
- if (!conditionComponents.isEmpty()) {
- rt.conditionComponents = conditionComponents
- .toArray(new ComponentName[conditionComponents.size()]);
- rt.conditionIds = conditionIds.toArray(new Uri[conditionIds.size()]);
- }
return rt;
}
if (type == XmlPullParser.START_TAG) {
@@ -314,31 +287,13 @@ public class ZenModeConfig implements Parcelable {
if (rt.allowFrom < SOURCE_ANYONE || rt.allowFrom > MAX_SOURCE) {
throw new IndexOutOfBoundsException("bad source in config:" + rt.allowFrom);
}
- } else if (SLEEP_TAG.equals(tag)) {
- final String mode = parser.getAttributeValue(null, SLEEP_ATT_MODE);
- rt.sleepMode = isValidSleepMode(mode)? mode : null;
- rt.sleepNone = safeBoolean(parser, SLEEP_ATT_NONE, false);
- final int startHour = safeInt(parser, SLEEP_ATT_START_HR, 0);
- final int startMinute = safeInt(parser, SLEEP_ATT_START_MIN, 0);
- final int endHour = safeInt(parser, SLEEP_ATT_END_HR, 0);
- final int endMinute = safeInt(parser, SLEEP_ATT_END_MIN, 0);
- rt.sleepStartHour = isValidHour(startHour) ? startHour : 0;
- rt.sleepStartMinute = isValidMinute(startMinute) ? startMinute : 0;
- rt.sleepEndHour = isValidHour(endHour) ? endHour : 0;
- rt.sleepEndMinute = isValidMinute(endMinute) ? endMinute : 0;
- } else if (CONDITION_TAG.equals(tag)) {
- final ComponentName component =
- safeComponentName(parser, CONDITION_ATT_COMPONENT);
- final Uri conditionId = safeUri(parser, CONDITION_ATT_ID);
- if (component != null && conditionId != null) {
- conditionComponents.add(component);
- conditionIds.add(conditionId);
- }
- } else if (EXIT_CONDITION_TAG.equals(tag)) {
- rt.exitCondition = readConditionXml(parser);
- if (rt.exitCondition != null) {
- rt.exitConditionComponent =
- safeComponentName(parser, EXIT_CONDITION_ATT_COMPONENT);
+ } else if (MANUAL_TAG.equals(tag)) {
+ rt.manualRule = readRuleXml(parser);
+ } else if (AUTOMATIC_TAG.equals(tag)) {
+ final String id = parser.getAttributeValue(null, RULE_ATT_ID);
+ final ZenRule automaticRule = readRuleXml(parser);
+ if (id != null && automaticRule != null) {
+ rt.automaticRules.put(id, automaticRule);
}
}
}
@@ -358,39 +313,61 @@ public class ZenModeConfig implements Parcelable {
out.attribute(null, ALLOW_ATT_FROM, Integer.toString(allowFrom));
out.endTag(null, ALLOW_TAG);
- out.startTag(null, SLEEP_TAG);
- if (sleepMode != null) {
- out.attribute(null, SLEEP_ATT_MODE, sleepMode);
- }
- out.attribute(null, SLEEP_ATT_NONE, Boolean.toString(sleepNone));
- out.attribute(null, SLEEP_ATT_START_HR, Integer.toString(sleepStartHour));
- out.attribute(null, SLEEP_ATT_START_MIN, Integer.toString(sleepStartMinute));
- out.attribute(null, SLEEP_ATT_END_HR, Integer.toString(sleepEndHour));
- out.attribute(null, SLEEP_ATT_END_MIN, Integer.toString(sleepEndMinute));
- out.endTag(null, SLEEP_TAG);
-
- if (conditionComponents != null && conditionIds != null
- && conditionComponents.length == conditionIds.length) {
- for (int i = 0; i < conditionComponents.length; i++) {
- out.startTag(null, CONDITION_TAG);
- out.attribute(null, CONDITION_ATT_COMPONENT,
- conditionComponents[i].flattenToString());
- out.attribute(null, CONDITION_ATT_ID, conditionIds[i].toString());
- out.endTag(null, CONDITION_TAG);
- }
+ if (manualRule != null) {
+ out.startTag(null, MANUAL_TAG);
+ writeRuleXml(manualRule, out);
+ out.endTag(null, MANUAL_TAG);
}
- if (exitCondition != null && exitConditionComponent != null) {
- out.startTag(null, EXIT_CONDITION_TAG);
- out.attribute(null, EXIT_CONDITION_ATT_COMPONENT,
- exitConditionComponent.flattenToString());
- writeConditionXml(exitCondition, out);
- out.endTag(null, EXIT_CONDITION_TAG);
+ final int N = automaticRules.size();
+ for (int i = 0; i < N; i++) {
+ final String id = automaticRules.keyAt(i);
+ final ZenRule automaticRule = automaticRules.valueAt(i);
+ out.startTag(null, AUTOMATIC_TAG);
+ out.attribute(null, RULE_ATT_ID, id);
+ writeRuleXml(automaticRule, out);
+ out.endTag(null, AUTOMATIC_TAG);
}
out.endTag(null, ZEN_TAG);
}
+ public static ZenRule readRuleXml(XmlPullParser parser) {
+ final ZenRule rt = new ZenRule();
+ rt.enabled = safeBoolean(parser, RULE_ATT_ENABLED, true);
+ rt.snoozing = safeBoolean(parser, RULE_ATT_SNOOZING, false);
+ rt.name = parser.getAttributeValue(null, RULE_ATT_NAME);
+ final String zen = parser.getAttributeValue(null, RULE_ATT_ZEN);
+ rt.zenMode = tryParseZenMode(zen, -1);
+ if (rt.zenMode == -1) {
+ Slog.w(TAG, "Bad zen mode in rule xml:" + zen);
+ return null;
+ }
+ rt.conditionId = safeUri(parser, RULE_ATT_CONDITION_ID);
+ rt.component = safeComponentName(parser, RULE_ATT_COMPONENT);
+ rt.condition = readConditionXml(parser);
+ return rt.condition != null ? rt : null;
+ }
+
+ public static void writeRuleXml(ZenRule rule, XmlSerializer out) throws IOException {
+ out.attribute(null, RULE_ATT_ENABLED, Boolean.toString(rule.enabled));
+ out.attribute(null, RULE_ATT_SNOOZING, Boolean.toString(rule.snoozing));
+ if (rule.name != null) {
+ out.attribute(null, RULE_ATT_NAME, rule.name);
+ }
+ out.attribute(null, RULE_ATT_ZEN, Integer.toString(rule.zenMode));
+ if (rule.component != null) {
+ out.attribute(null, RULE_ATT_COMPONENT, rule.component.flattenToString());
+ }
+ if (rule.conditionId != null) {
+ out.attribute(null, RULE_ATT_CONDITION_ID, rule.conditionId.toString());
+ }
+ if (rule.condition != null) {
+ writeConditionXml(rule.condition, out);
+ }
+ }
+
public static Condition readConditionXml(XmlPullParser parser) {
final Uri id = safeUri(parser, CONDITION_ATT_ID);
+ if (id == null) return null;
final String summary = parser.getAttributeValue(null, CONDITION_ATT_SUMMARY);
final String line1 = parser.getAttributeValue(null, CONDITION_ATT_LINE1);
final String line2 = parser.getAttributeValue(null, CONDITION_ATT_LINE2);
@@ -446,6 +423,14 @@ public class ZenModeConfig implements Parcelable {
return Uri.parse(val);
}
+ public ArraySet<String> getAutomaticRuleNames() {
+ final ArraySet<String> rt = new ArraySet<String>();
+ for (int i = 0; i < automaticRules.size(); i++) {
+ rt.add(automaticRules.valueAt(i).name);
+ }
+ return rt;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -475,17 +460,6 @@ public class ZenModeConfig implements Parcelable {
}
};
- public DowntimeInfo toDowntimeInfo() {
- final DowntimeInfo downtime = new DowntimeInfo();
- downtime.startHour = sleepStartHour;
- downtime.startMinute = sleepStartMinute;
- downtime.endHour = sleepEndHour;
- downtime.endMinute = sleepEndMinute;
- downtime.mode = sleepMode;
- downtime.none = sleepNone;
- return downtime;
- }
-
public static Condition toTimeCondition(Context context, int minutesFromNow, int userHandle) {
final long now = System.currentTimeMillis();
final long millis = minutesFromNow == 0 ? ZERO_VALUE_MS : minutesFromNow * MINUTES_MS;
@@ -548,38 +522,77 @@ public class ZenModeConfig implements Parcelable {
return tryParseCountdownConditionId(conditionId) != 0;
}
- // Built-in downtime conditions
- // e.g. condition://android/downtime?start=10.00&end=7.00&mode=days%3A5%2C6&none=false
- public static final String DOWNTIME_PATH = "downtime";
+ // built-in schedule conditions
+ public static final String SCHEDULE_PATH = "schedule";
+
+ public static class ScheduleInfo {
+ public int[] days;
+ public int startHour;
+ public int startMinute;
+ public int endHour;
+ public int endMinute;
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof ScheduleInfo)) return false;
+ final ScheduleInfo other = (ScheduleInfo) o;
+ return toDayList(days).equals(toDayList(other.days))
+ && startHour == other.startHour
+ && startMinute == other.startMinute
+ && endHour == other.endHour
+ && endMinute == other.endMinute;
+ }
+
+ public ScheduleInfo copy() {
+ final ScheduleInfo rt = new ScheduleInfo();
+ if (days != null) {
+ rt.days = new int[days.length];
+ System.arraycopy(days, 0, rt.days, 0, days.length);
+ }
+ rt.startHour = startHour;
+ rt.startMinute = startMinute;
+ rt.endHour = endHour;
+ rt.endMinute = endMinute;
+ return rt;
+ }
+ }
- public static Uri toDowntimeConditionId(DowntimeInfo downtime) {
+ public static Uri toScheduleConditionId(ScheduleInfo schedule) {
return new Uri.Builder().scheme(Condition.SCHEME)
.authority(SYSTEM_AUTHORITY)
- .appendPath(DOWNTIME_PATH)
- .appendQueryParameter("start", downtime.startHour + "." + downtime.startMinute)
- .appendQueryParameter("end", downtime.endHour + "." + downtime.endMinute)
- .appendQueryParameter("mode", downtime.mode)
- .appendQueryParameter("none", Boolean.toString(downtime.none))
+ .appendPath(SCHEDULE_PATH)
+ .appendQueryParameter("days", toDayList(schedule.days))
+ .appendQueryParameter("start", schedule.startHour + "." + schedule.startMinute)
+ .appendQueryParameter("end", schedule.endHour + "." + schedule.endMinute)
.build();
}
- public static DowntimeInfo tryParseDowntimeConditionId(Uri conditionId) {
- if (!Condition.isValidId(conditionId, SYSTEM_AUTHORITY)
- || conditionId.getPathSegments().size() != 1
- || !DOWNTIME_PATH.equals(conditionId.getPathSegments().get(0))) {
- return null;
- }
+ public static boolean isValidScheduleConditionId(Uri conditionId) {
+ return tryParseScheduleConditionId(conditionId) != null;
+ }
+
+ public static ScheduleInfo tryParseScheduleConditionId(Uri conditionId) {
+ final boolean isSchedule = conditionId != null
+ && conditionId.getScheme().equals(Condition.SCHEME)
+ && conditionId.getAuthority().equals(ZenModeConfig.SYSTEM_AUTHORITY)
+ && conditionId.getPathSegments().size() == 1
+ && conditionId.getPathSegments().get(0).equals(ZenModeConfig.SCHEDULE_PATH);
+ if (!isSchedule) return null;
final int[] start = tryParseHourAndMinute(conditionId.getQueryParameter("start"));
final int[] end = tryParseHourAndMinute(conditionId.getQueryParameter("end"));
if (start == null || end == null) return null;
- final DowntimeInfo downtime = new DowntimeInfo();
- downtime.startHour = start[0];
- downtime.startMinute = start[1];
- downtime.endHour = end[0];
- downtime.endMinute = end[1];
- downtime.mode = conditionId.getQueryParameter("mode");
- downtime.none = Boolean.toString(true).equals(conditionId.getQueryParameter("none"));
- return downtime;
+ final ScheduleInfo rt = new ScheduleInfo();
+ rt.days = tryParseDayList(conditionId.getQueryParameter("days"), "\\.");
+ rt.startHour = start[0];
+ rt.startMinute = start[1];
+ rt.endHour = end[0];
+ rt.endMinute = end[1];
+ return rt;
}
private static int[] tryParseHourAndMinute(String value) {
@@ -591,36 +604,268 @@ public class ZenModeConfig implements Parcelable {
return isValidHour(hour) && isValidMinute(minute) ? new int[] { hour, minute } : null;
}
- public static boolean isValidDowntimeConditionId(Uri conditionId) {
- return tryParseDowntimeConditionId(conditionId) != null;
+ private static int tryParseZenMode(String value, int defValue) {
+ final int rt = tryParseInt(value, defValue);
+ return Global.isValidZenMode(rt) ? rt : defValue;
}
- public static class DowntimeInfo {
- public int startHour; // 0-23
- public int startMinute; // 0-59
- public int endHour;
- public int endMinute;
- public String mode;
- public boolean none;
+ public String newRuleId() {
+ return UUID.randomUUID().toString().replace("-", "");
+ }
+
+ public static String getConditionLine1(Context context, ZenModeConfig config,
+ int userHandle) {
+ return getConditionLine(context, config, userHandle, true /*useLine1*/);
+ }
+
+ public static String getConditionSummary(Context context, ZenModeConfig config,
+ int userHandle) {
+ return getConditionLine(context, config, userHandle, false /*useLine1*/);
+ }
+
+ private static String getConditionLine(Context context, ZenModeConfig config,
+ int userHandle, boolean useLine1) {
+ if (config == null) return "";
+ if (config.manualRule != null) {
+ final Uri id = config.manualRule.conditionId;
+ if (id == null) {
+ return context.getString(com.android.internal.R.string.zen_mode_forever);
+ }
+ final long time = tryParseCountdownConditionId(id);
+ Condition c = config.manualRule.condition;
+ if (time > 0) {
+ final long now = System.currentTimeMillis();
+ final long span = time - now;
+ c = toTimeCondition(context,
+ time, Math.round(span / (float) MINUTES_MS), now, userHandle);
+ }
+ final String rt = c == null ? "" : useLine1 ? c.line1 : c.summary;
+ return TextUtils.isEmpty(rt) ? "" : rt;
+ }
+ String summary = "";
+ for (ZenRule automaticRule : config.automaticRules.values()) {
+ if (automaticRule.enabled && !automaticRule.snoozing
+ && automaticRule.isTrueOrUnknown()) {
+ if (summary.isEmpty()) {
+ summary = automaticRule.name;
+ } else {
+ summary = context.getResources()
+ .getString(R.string.zen_mode_rule_name_combination, summary,
+ automaticRule.name);
+ }
+ }
+ }
+ return summary;
+ }
+
+ public static class ZenRule implements Parcelable {
+ public boolean enabled;
+ public boolean snoozing; // user manually disabled this instance
+ public String name; // required for automatic (unique)
+ public int zenMode;
+ public Uri conditionId; // required for automatic
+ public Condition condition; // optional
+ public ComponentName component; // optional
+
+ public ZenRule() { }
+
+ public ZenRule(Parcel source) {
+ enabled = source.readInt() == 1;
+ snoozing = source.readInt() == 1;
+ if (source.readInt() == 1) {
+ name = source.readString();
+ }
+ zenMode = source.readInt();
+ conditionId = source.readParcelable(null);
+ condition = source.readParcelable(null);
+ component = source.readParcelable(null);
+ }
@Override
- public int hashCode() {
+ public int describeContents() {
return 0;
}
@Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(enabled ? 1 : 0);
+ dest.writeInt(snoozing ? 1 : 0);
+ if (name != null) {
+ dest.writeInt(1);
+ dest.writeString(name);
+ } else {
+ dest.writeInt(0);
+ }
+ dest.writeInt(zenMode);
+ dest.writeParcelable(conditionId, 0);
+ dest.writeParcelable(condition, 0);
+ dest.writeParcelable(component, 0);
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder(ZenRule.class.getSimpleName()).append('[')
+ .append("enabled=").append(enabled)
+ .append(",snoozing=").append(snoozing)
+ .append(",name=").append(name)
+ .append(",zenMode=").append(Global.zenModeToString(zenMode))
+ .append(",conditionId=").append(conditionId)
+ .append(",condition=").append(condition)
+ .append(",component=").append(component)
+ .append(']').toString();
+ }
+
+ @Override
public boolean equals(Object o) {
- if (!(o instanceof DowntimeInfo)) return false;
- final DowntimeInfo other = (DowntimeInfo) o;
- return startHour == other.startHour
- && startMinute == other.startMinute
- && endHour == other.endHour
- && endMinute == other.endMinute
- && Objects.equals(mode, other.mode)
- && none == other.none;
+ if (!(o instanceof ZenRule)) return false;
+ if (o == this) return true;
+ final ZenRule other = (ZenRule) o;
+ return other.enabled == enabled
+ && other.snoozing == snoozing
+ && Objects.equals(other.name, name)
+ && other.zenMode == zenMode
+ && Objects.equals(other.conditionId, conditionId)
+ && Objects.equals(other.condition, condition)
+ && Objects.equals(other.component, component);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition,
+ component);
+ }
+
+ public boolean isTrueOrUnknown() {
+ return condition == null || condition.state == Condition.STATE_TRUE
+ || condition.state == Condition.STATE_UNKNOWN;
+ }
+
+ public static final Parcelable.Creator<ZenRule> CREATOR
+ = new Parcelable.Creator<ZenRule>() {
+ @Override
+ public ZenRule createFromParcel(Parcel source) {
+ return new ZenRule(source);
+ }
+ @Override
+ public ZenRule[] newArray(int size) {
+ return new ZenRule[size];
+ }
+ };
+ }
+
+ // Legacy config
+ public static final class XmlV1 {
+ public static final String SLEEP_MODE_NIGHTS = "nights";
+ public static final String SLEEP_MODE_WEEKNIGHTS = "weeknights";
+ public static final String SLEEP_MODE_DAYS_PREFIX = "days:";
+
+ private static final String EXIT_CONDITION_TAG = "exitCondition";
+ private static final String EXIT_CONDITION_ATT_COMPONENT = "component";
+ private static final String SLEEP_TAG = "sleep";
+ private static final String SLEEP_ATT_MODE = "mode";
+ private static final String SLEEP_ATT_NONE = "none";
+
+ private static final String SLEEP_ATT_START_HR = "startHour";
+ private static final String SLEEP_ATT_START_MIN = "startMin";
+ private static final String SLEEP_ATT_END_HR = "endHour";
+ private static final String SLEEP_ATT_END_MIN = "endMin";
+
+ public boolean allowCalls;
+ public boolean allowMessages;
+ public boolean allowReminders = DEFAULT_ALLOW_REMINDERS;
+ public boolean allowEvents = DEFAULT_ALLOW_EVENTS;
+ public int allowFrom = SOURCE_ANYONE;
+
+ public String sleepMode; // nights, weeknights, days:1,2,3 Calendar.days
+ public int sleepStartHour; // 0-23
+ public int sleepStartMinute; // 0-59
+ public int sleepEndHour;
+ public int sleepEndMinute;
+ public boolean sleepNone; // false = priority, true = none
+ public ComponentName[] conditionComponents;
+ public Uri[] conditionIds;
+ public Condition exitCondition; // manual exit condition
+ public ComponentName exitConditionComponent; // manual exit condition component
+
+ private static boolean isValidSleepMode(String sleepMode) {
+ return sleepMode == null || sleepMode.equals(SLEEP_MODE_NIGHTS)
+ || sleepMode.equals(SLEEP_MODE_WEEKNIGHTS) || tryParseDays(sleepMode) != null;
+ }
+
+ public static int[] tryParseDays(String sleepMode) {
+ if (sleepMode == null) return null;
+ sleepMode = sleepMode.trim();
+ if (SLEEP_MODE_NIGHTS.equals(sleepMode)) return ALL_DAYS;
+ if (SLEEP_MODE_WEEKNIGHTS.equals(sleepMode)) return WEEKNIGHT_DAYS;
+ if (!sleepMode.startsWith(SLEEP_MODE_DAYS_PREFIX)) return null;
+ if (sleepMode.equals(SLEEP_MODE_DAYS_PREFIX)) return null;
+ return tryParseDayList(sleepMode.substring(SLEEP_MODE_DAYS_PREFIX.length()), ",");
+ }
+
+ public static XmlV1 readXml(XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+ int type;
+ String tag;
+ XmlV1 rt = new XmlV1();
+ final ArrayList<ComponentName> conditionComponents = new ArrayList<ComponentName>();
+ final ArrayList<Uri> conditionIds = new ArrayList<Uri>();
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ tag = parser.getName();
+ if (type == XmlPullParser.END_TAG && ZEN_TAG.equals(tag)) {
+ if (!conditionComponents.isEmpty()) {
+ rt.conditionComponents = conditionComponents
+ .toArray(new ComponentName[conditionComponents.size()]);
+ rt.conditionIds = conditionIds.toArray(new Uri[conditionIds.size()]);
+ }
+ return rt;
+ }
+ if (type == XmlPullParser.START_TAG) {
+ if (ALLOW_TAG.equals(tag)) {
+ rt.allowCalls = safeBoolean(parser, ALLOW_ATT_CALLS, false);
+ rt.allowMessages = safeBoolean(parser, ALLOW_ATT_MESSAGES, false);
+ rt.allowReminders = safeBoolean(parser, ALLOW_ATT_REMINDERS,
+ DEFAULT_ALLOW_REMINDERS);
+ rt.allowEvents = safeBoolean(parser, ALLOW_ATT_EVENTS,
+ DEFAULT_ALLOW_EVENTS);
+ rt.allowFrom = safeInt(parser, ALLOW_ATT_FROM, SOURCE_ANYONE);
+ if (rt.allowFrom < SOURCE_ANYONE || rt.allowFrom > MAX_SOURCE) {
+ throw new IndexOutOfBoundsException("bad source in config:"
+ + rt.allowFrom);
+ }
+ } else if (SLEEP_TAG.equals(tag)) {
+ final String mode = parser.getAttributeValue(null, SLEEP_ATT_MODE);
+ rt.sleepMode = isValidSleepMode(mode)? mode : null;
+ rt.sleepNone = safeBoolean(parser, SLEEP_ATT_NONE, false);
+ final int startHour = safeInt(parser, SLEEP_ATT_START_HR, 0);
+ final int startMinute = safeInt(parser, SLEEP_ATT_START_MIN, 0);
+ final int endHour = safeInt(parser, SLEEP_ATT_END_HR, 0);
+ final int endMinute = safeInt(parser, SLEEP_ATT_END_MIN, 0);
+ rt.sleepStartHour = isValidHour(startHour) ? startHour : 0;
+ rt.sleepStartMinute = isValidMinute(startMinute) ? startMinute : 0;
+ rt.sleepEndHour = isValidHour(endHour) ? endHour : 0;
+ rt.sleepEndMinute = isValidMinute(endMinute) ? endMinute : 0;
+ } else if (CONDITION_TAG.equals(tag)) {
+ final ComponentName component =
+ safeComponentName(parser, CONDITION_ATT_COMPONENT);
+ final Uri conditionId = safeUri(parser, CONDITION_ATT_ID);
+ if (component != null && conditionId != null) {
+ conditionComponents.add(component);
+ conditionIds.add(conditionId);
+ }
+ } else if (EXIT_CONDITION_TAG.equals(tag)) {
+ rt.exitCondition = readConditionXml(parser);
+ if (rt.exitCondition != null) {
+ rt.exitConditionComponent =
+ safeComponentName(parser, EXIT_CONDITION_ATT_COMPONENT);
+ }
+ }
+ }
+ }
+ throw new IllegalStateException("Failed to reach END_DOCUMENT");
}
}
- // built-in next alarm conditions
- public static final String NEXT_ALARM_PATH = "next_alarm";
+ public interface Migration {
+ ZenModeConfig migrate(XmlV1 v1);
+ }
}
diff --git a/core/java/android/text/method/AllCapsTransformationMethod.java b/core/java/android/text/method/AllCapsTransformationMethod.java
index f9920dd..0cea821 100644
--- a/core/java/android/text/method/AllCapsTransformationMethod.java
+++ b/core/java/android/text/method/AllCapsTransformationMethod.java
@@ -19,6 +19,7 @@ import android.content.Context;
import android.graphics.Rect;
import android.util.Log;
import android.view.View;
+import android.widget.TextView;
import java.util.Locale;
@@ -39,11 +40,23 @@ public class AllCapsTransformationMethod implements TransformationMethod2 {
@Override
public CharSequence getTransformation(CharSequence source, View view) {
- if (mEnabled) {
- return source != null ? source.toString().toUpperCase(mLocale) : null;
+ if (!mEnabled) {
+ Log.w(TAG, "Caller did not enable length changes; not transforming text");
+ return source;
}
- Log.w(TAG, "Caller did not enable length changes; not transforming text");
- return source;
+
+ if (source == null) {
+ return null;
+ }
+
+ Locale locale = null;
+ if (view instanceof TextView) {
+ locale = ((TextView)view).getTextLocale();
+ }
+ if (locale == null) {
+ locale = mLocale;
+ }
+ return source.toString().toUpperCase(locale);
}
@Override
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index 63607fa..07c1ec3 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -22,6 +22,8 @@ import android.text.*;
import android.text.method.TextKeyListener.Capitalize;
import android.widget.TextView;
+import java.text.BreakIterator;
+
/**
* Abstract base class for key listeners.
*
@@ -63,9 +65,9 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener
private boolean backspaceOrForwardDelete(View view, Editable content, int keyCode,
KeyEvent event, boolean isForwardDelete) {
- // Ensure the key event does not have modifiers except ALT or SHIFT.
+ // Ensure the key event does not have modifiers except ALT or SHIFT or CTRL.
if (!KeyEvent.metaStateHasNoModifiers(event.getMetaState()
- & ~(KeyEvent.META_SHIFT_MASK | KeyEvent.META_ALT_MASK))) {
+ & ~(KeyEvent.META_SHIFT_MASK | KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK))) {
return false;
}
@@ -74,18 +76,28 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener
return true;
}
- // Alt+Backspace or Alt+ForwardDelete deletes the current line, if possible.
- if (getMetaState(content, META_ALT_ON, event) == 1) {
- if (deleteLine(view, content)) {
- return true;
+ // MetaKeyKeyListener doesn't track control key state. Need to check the KeyEvent instead.
+ boolean isCtrlActive = ((event.getMetaState() & KeyEvent.META_CTRL_ON) != 0);
+ boolean isShiftActive = (getMetaState(content, META_SHIFT_ON, event) == 1);
+ boolean isAltActive = (getMetaState(content, META_ALT_ON, event) == 1);
+
+ if (isCtrlActive) {
+ if (isAltActive || isShiftActive) {
+ // Ctrl+Alt, Ctrl+Shift, Ctrl+Alt+Shift should not delete any characters.
+ return false;
}
+ return deleteUntilWordBoundary(view, content, isForwardDelete);
+ }
+
+ // Alt+Backspace or Alt+ForwardDelete deletes the current line, if possible.
+ if (isAltActive && deleteLine(view, content)) {
+ return true;
}
// Delete a character.
final int start = Selection.getSelectionEnd(content);
final int end;
- if (isForwardDelete || event.isShiftPressed()
- || getMetaState(content, META_SHIFT_ON) == 1) {
+ if (isForwardDelete || event.isShiftPressed() || isShiftActive) {
end = TextUtils.getOffsetAfter(content, start);
} else {
end = TextUtils.getOffsetBefore(content, start);
@@ -97,6 +109,54 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener
return false;
}
+ private boolean deleteUntilWordBoundary(View view, Editable content, boolean isForwardDelete) {
+ int currentCursorOffset = Selection.getSelectionStart(content);
+
+ // If there is a selection, do nothing.
+ if (currentCursorOffset != Selection.getSelectionEnd(content)) {
+ return false;
+ }
+
+ // Early exit if there is no contents to delete.
+ if ((!isForwardDelete && currentCursorOffset == 0) ||
+ (isForwardDelete && currentCursorOffset == content.length())) {
+ return false;
+ }
+
+ WordIterator wordIterator = null;
+ if (view instanceof TextView) {
+ wordIterator = ((TextView)view).getWordIterator();
+ }
+
+ if (wordIterator == null) {
+ // Default locale is used for WordIterator since the appropriate locale is not clear
+ // here.
+ // TODO: Use appropriate locale for WordIterator.
+ wordIterator = new WordIterator();
+ }
+
+ int deleteFrom;
+ int deleteTo;
+
+ if (isForwardDelete) {
+ deleteFrom = currentCursorOffset;
+ wordIterator.setCharSequence(content, deleteFrom, content.length());
+ deleteTo = wordIterator.following(currentCursorOffset);
+ if (deleteTo == BreakIterator.DONE) {
+ deleteTo = content.length();
+ }
+ } else {
+ deleteTo = currentCursorOffset;
+ wordIterator.setCharSequence(content, 0, deleteTo);
+ deleteFrom = wordIterator.preceding(currentCursorOffset);
+ if (deleteFrom == BreakIterator.DONE) {
+ deleteFrom = 0;
+ }
+ }
+ content.delete(deleteFrom, deleteTo);
+ return true;
+ }
+
private boolean deleteSelection(View view, Editable content) {
int selectionStart = Selection.getSelectionStart(content);
int selectionEnd = Selection.getSelectionEnd(content);
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index 0b70fdb..5209f90 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -430,7 +430,6 @@ public class TransitionManager {
* Ends all pending and ongoing transitions on the specified scene root.
*
* @param sceneRoot The root of the View hierarchy to end transitions on.
- * @hide
*/
public static void endTransitions(final ViewGroup sceneRoot) {
sPendingTransitions.remove(sceneRoot);
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 2eac549..1ee4780 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -49,7 +49,6 @@ public final class InputDevice implements Parcelable {
private final String mName;
private final int mVendorId;
private final int mProductId;
- private final String mUniqueId;
private final String mDescriptor;
private final InputDeviceIdentifier mIdentifier;
private final boolean mIsExternal;
@@ -57,6 +56,7 @@ public final class InputDevice implements Parcelable {
private final int mKeyboardType;
private final KeyCharacterMap mKeyCharacterMap;
private final boolean mHasVibrator;
+ private final boolean mHasMic;
private final boolean mHasButtonUnderPad;
private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>();
@@ -357,8 +357,8 @@ public final class InputDevice implements Parcelable {
// Called by native code.
private InputDevice(int id, int generation, int controllerNumber, String name, int vendorId,
- int productId, String uniqueId, String descriptor, boolean isExternal, int sources,
- int keyboardType, KeyCharacterMap keyCharacterMap, boolean hasVibrator,
+ int productId, String descriptor, boolean isExternal, int sources, int keyboardType,
+ KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasMic,
boolean hasButtonUnderPad) {
mId = id;
mGeneration = generation;
@@ -366,13 +366,13 @@ public final class InputDevice implements Parcelable {
mName = name;
mVendorId = vendorId;
mProductId = productId;
- mUniqueId = uniqueId;
mDescriptor = descriptor;
mIsExternal = isExternal;
mSources = sources;
mKeyboardType = keyboardType;
mKeyCharacterMap = keyCharacterMap;
mHasVibrator = hasVibrator;
+ mHasMic = hasMic;
mHasButtonUnderPad = hasButtonUnderPad;
mIdentifier = new InputDeviceIdentifier(descriptor, vendorId, productId);
}
@@ -384,13 +384,13 @@ public final class InputDevice implements Parcelable {
mName = in.readString();
mVendorId = in.readInt();
mProductId = in.readInt();
- mUniqueId = in.readString();
mDescriptor = in.readString();
mIsExternal = in.readInt() != 0;
mSources = in.readInt();
mKeyboardType = in.readInt();
mKeyCharacterMap = KeyCharacterMap.CREATOR.createFromParcel(in);
mHasVibrator = in.readInt() != 0;
+ mHasMic = in.readInt() != 0;
mHasButtonUnderPad = in.readInt() != 0;
mIdentifier = new InputDeviceIdentifier(mDescriptor, mVendorId, mProductId);
@@ -509,23 +509,6 @@ public final class InputDevice implements Parcelable {
}
/**
- * Gets the vendor's unique id for the given device, if available.
- * <p>
- * A vendor may assign a unique id to a device (e.g., MAC address for
- * Bluetooth devices). A null value will be assigned where a unique id is
- * not available.
- * </p><p>
- * This method is dependent on the vendor, whereas {@link #getDescriptor}
- * attempts to create a unique id even when the vendor has not provided one.
- * </p>
- *
- * @return The unique id of a given device
- */
- public String getUniqueId() {
- return mUniqueId;
- }
-
- /**
* Gets the input device descriptor, which is a stable identifier for an input device.
* <p>
* An input device descriptor uniquely identifies an input device. Its value
@@ -737,6 +720,14 @@ public final class InputDevice implements Parcelable {
}
/**
+ * Reports whether the device has a built-in microphone.
+ * @return Whether the device has a built-in microphone.
+ */
+ public boolean hasMic() {
+ return mHasMic;
+ }
+
+ /**
* Reports whether the device has a button under its touchpad
* @return Whether the device has a button under its touchpad
* @hide
@@ -864,13 +855,13 @@ public final class InputDevice implements Parcelable {
out.writeString(mName);
out.writeInt(mVendorId);
out.writeInt(mProductId);
- out.writeString(mUniqueId);
out.writeString(mDescriptor);
out.writeInt(mIsExternal ? 1 : 0);
out.writeInt(mSources);
out.writeInt(mKeyboardType);
mKeyCharacterMap.writeToParcel(out, flags);
out.writeInt(mHasVibrator ? 1 : 0);
+ out.writeInt(mHasMic ? 1 : 0);
out.writeInt(mHasButtonUnderPad ? 1 : 0);
final int numRanges = mMotionRanges.size();
@@ -916,6 +907,8 @@ public final class InputDevice implements Parcelable {
description.append(" Has Vibrator: ").append(mHasVibrator).append("\n");
+ description.append(" Has mic: ").append(mHasMic).append("\n");
+
description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" (");
appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard");
appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad");
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index 36bce0b..f951dc2 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -397,7 +397,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter
public void updateMenuView(boolean cleared) {
final ViewGroup menuViewParent = (ViewGroup) ((View) mMenuView).getParent();
if (menuViewParent != null) {
- setupItemAnimations();
+// setupItemAnimations();
ActionBarTransition.beginDelayedTransition(menuViewParent);
}
super.updateMenuView(cleared);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index c0908b3..5fb0c92 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -557,7 +557,7 @@ public class Editor {
}
}
- private void hideInsertionPointCursorController() {
+ void hideInsertionPointCursorController() {
if (mInsertionPointCursorController != null) {
mInsertionPointCursorController.hide();
}
@@ -1672,7 +1672,8 @@ public class Editor {
return false;
}
ActionMode.Callback actionModeCallback = new SelectionActionModeCallback();
- mSelectionActionMode = mTextView.startActionMode(actionModeCallback);
+ mSelectionActionMode = mTextView.startActionMode(
+ actionModeCallback, ActionMode.TYPE_FLOATING);
return mSelectionActionMode != null;
}
@@ -1706,7 +1707,8 @@ public class Editor {
// immediately hide the newly created action bar and would be visually distracting.
if (!willExtract) {
ActionMode.Callback actionModeCallback = new SelectionActionModeCallback();
- mSelectionActionMode = mTextView.startActionMode(actionModeCallback);
+ mSelectionActionMode = mTextView.startActionMode(
+ actionModeCallback, ActionMode.TYPE_FLOATING);
}
final boolean selectionStarted = mSelectionActionMode != null || willExtract;
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 21213ac..4b5407a 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -46,6 +46,8 @@ import android.view.ViewGroupOverlay;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView.ScaleType;
+import com.android.internal.R;
+
/**
* Helper class for AbsListView to draw and control the Fast Scroll thumb
*/
@@ -82,6 +84,10 @@ class FastScroller {
private static final int OVERLAY_AT_THUMB = 1;
private static final int OVERLAY_ABOVE_THUMB = 2;
+ // Positions for thumb in relation to track.
+ private static final int THUMB_POSITION_MIDPOINT = 0;
+ private static final int THUMB_POSITION_INSIDE = 1;
+
// Indices for mPreviewResId.
private static final int PREVIEW_LEFT = 0;
private static final int PREVIEW_RIGHT = 1;
@@ -100,7 +106,6 @@ class FastScroller {
private final ImageView mThumbImage;
private final ImageView mTrackImage;
private final View mPreviewImage;
-
/**
* Preview image resource IDs for left- and right-aligned layouts. See
* {@link #PREVIEW_LEFT} and {@link #PREVIEW_RIGHT}.
@@ -130,6 +135,11 @@ class FastScroller {
private Drawable mThumbDrawable;
private Drawable mTrackDrawable;
private int mTextAppearance;
+ private int mThumbPosition;
+
+ // Used to convert between y-coordinate and thumb position within track.
+ private float mThumbOffset;
+ private float mThumbRange;
/** Total width of decorations. */
private int mWidth;
@@ -278,7 +288,6 @@ class FastScroller {
}
private void updateAppearance() {
- final Context context = mList.getContext();
int width = 0;
// Add track to overlay if it has an image.
@@ -298,12 +307,9 @@ class FastScroller {
// Account for minimum thumb width.
mWidth = Math.max(width, mThumbMinWidth);
- mPreviewImage.setMinimumWidth(mPreviewMinWidth);
- mPreviewImage.setMinimumHeight(mPreviewMinHeight);
-
if (mTextAppearance != 0) {
- mPrimaryText.setTextAppearance(context, mTextAppearance);
- mSecondaryText.setTextAppearance(context, mTextAppearance);
+ mPrimaryText.setTextAppearance(mTextAppearance);
+ mSecondaryText.setTextAppearance(mTextAppearance);
}
if (mTextColor != null) {
@@ -316,13 +322,11 @@ class FastScroller {
mSecondaryText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize);
}
- final int textMinSize = Math.max(0, mPreviewMinHeight);
- mPrimaryText.setMinimumWidth(textMinSize);
- mPrimaryText.setMinimumHeight(textMinSize);
+ final int padding = mPreviewPadding;
mPrimaryText.setIncludeFontPadding(false);
- mSecondaryText.setMinimumWidth(textMinSize);
- mSecondaryText.setMinimumHeight(textMinSize);
+ mPrimaryText.setPadding(padding, padding, padding, padding);
mSecondaryText.setIncludeFontPadding(false);
+ mSecondaryText.setPadding(padding, padding, padding, padding);
refreshDrawablePressedState();
}
@@ -330,50 +334,53 @@ class FastScroller {
public void setStyle(@StyleRes int resId) {
final Context context = mList.getContext();
final TypedArray ta = context.obtainStyledAttributes(null,
- com.android.internal.R.styleable.FastScroll, android.R.attr.fastScrollStyle, resId);
+ R.styleable.FastScroll, R.attr.fastScrollStyle, resId);
final int N = ta.getIndexCount();
for (int i = 0; i < N; i++) {
final int index = ta.getIndex(i);
switch (index) {
- case com.android.internal.R.styleable.FastScroll_position:
+ case R.styleable.FastScroll_position:
mOverlayPosition = ta.getInt(index, OVERLAY_FLOATING);
break;
- case com.android.internal.R.styleable.FastScroll_backgroundLeft:
+ case R.styleable.FastScroll_backgroundLeft:
mPreviewResId[PREVIEW_LEFT] = ta.getResourceId(index, 0);
break;
- case com.android.internal.R.styleable.FastScroll_backgroundRight:
+ case R.styleable.FastScroll_backgroundRight:
mPreviewResId[PREVIEW_RIGHT] = ta.getResourceId(index, 0);
break;
- case com.android.internal.R.styleable.FastScroll_thumbDrawable:
+ case R.styleable.FastScroll_thumbDrawable:
mThumbDrawable = ta.getDrawable(index);
break;
- case com.android.internal.R.styleable.FastScroll_trackDrawable:
+ case R.styleable.FastScroll_trackDrawable:
mTrackDrawable = ta.getDrawable(index);
break;
- case com.android.internal.R.styleable.FastScroll_textAppearance:
+ case R.styleable.FastScroll_textAppearance:
mTextAppearance = ta.getResourceId(index, 0);
break;
- case com.android.internal.R.styleable.FastScroll_textColor:
+ case R.styleable.FastScroll_textColor:
mTextColor = ta.getColorStateList(index);
break;
- case com.android.internal.R.styleable.FastScroll_textSize:
+ case R.styleable.FastScroll_textSize:
mTextSize = ta.getDimensionPixelSize(index, 0);
break;
- case com.android.internal.R.styleable.FastScroll_minWidth:
+ case R.styleable.FastScroll_minWidth:
mPreviewMinWidth = ta.getDimensionPixelSize(index, 0);
break;
- case com.android.internal.R.styleable.FastScroll_minHeight:
+ case R.styleable.FastScroll_minHeight:
mPreviewMinHeight = ta.getDimensionPixelSize(index, 0);
break;
- case com.android.internal.R.styleable.FastScroll_thumbMinWidth:
+ case R.styleable.FastScroll_thumbMinWidth:
mThumbMinWidth = ta.getDimensionPixelSize(index, 0);
break;
- case com.android.internal.R.styleable.FastScroll_thumbMinHeight:
+ case R.styleable.FastScroll_thumbMinHeight:
mThumbMinHeight = ta.getDimensionPixelSize(index, 0);
break;
- case com.android.internal.R.styleable.FastScroll_padding:
+ case R.styleable.FastScroll_padding:
mPreviewPadding = ta.getDimensionPixelSize(index, 0);
break;
+ case R.styleable.FastScroll_thumbPosition:
+ mThumbPosition = ta.getInt(index, THUMB_POSITION_MIDPOINT);
+ break;
}
}
@@ -478,14 +485,16 @@ class FastScroller {
final int previewResId = mPreviewResId[mLayoutFromRight ? PREVIEW_RIGHT : PREVIEW_LEFT];
mPreviewImage.setBackgroundResource(previewResId);
- // Add extra padding for text.
- final Drawable background = mPreviewImage.getBackground();
- if (background != null) {
- final Rect padding = mTempBounds;
- background.getPadding(padding);
- padding.offset(mPreviewPadding, mPreviewPadding);
- mPreviewImage.setPadding(padding.left, padding.top, padding.right, padding.bottom);
- }
+ // Propagate padding to text min width/height.
+ final int textMinWidth = Math.max(0, mPreviewMinWidth - mPreviewImage.getPaddingLeft()
+ - mPreviewImage.getPaddingRight());
+ mPrimaryText.setMinimumWidth(textMinWidth);
+ mSecondaryText.setMinimumWidth(textMinWidth);
+
+ final int textMinHeight = Math.max(0, mPreviewMinHeight - mPreviewImage.getPaddingTop()
+ - mPreviewImage.getPaddingBottom());
+ mPrimaryText.setMinimumHeight(textMinHeight);
+ mSecondaryText.setMinimumHeight(textMinHeight);
// Requires re-layout.
updateLayout();
@@ -560,6 +569,8 @@ class FastScroller {
layoutThumb();
layoutTrack();
+ updateOffsetAndRange();
+
final Rect bounds = mTempBounds;
measurePreview(mPrimaryText, bounds);
applyLayout(mPrimaryText, bounds);
@@ -758,15 +769,45 @@ class FastScroller {
final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
track.measure(widthMeasureSpec, heightMeasureSpec);
+ final int top;
+ final int bottom;
+ if (mThumbPosition == THUMB_POSITION_INSIDE) {
+ top = container.top;
+ bottom = container.bottom;
+ } else {
+ final int thumbHalfHeight = thumb.getHeight() / 2;
+ top = container.top + thumbHalfHeight;
+ bottom = container.bottom - thumbHalfHeight;
+ }
+
final int trackWidth = track.getMeasuredWidth();
- final int thumbHalfHeight = thumb.getHeight() / 2;
final int left = thumb.getLeft() + (thumb.getWidth() - trackWidth) / 2;
final int right = left + trackWidth;
- final int top = container.top + thumbHalfHeight;
- final int bottom = container.bottom - thumbHalfHeight;
track.layout(left, top, right, bottom);
}
+ /**
+ * Updates the offset and range used to convert from absolute y-position to
+ * thumb position within the track.
+ */
+ private void updateOffsetAndRange() {
+ final View trackImage = mTrackImage;
+ final View thumbImage = mThumbImage;
+ final float min;
+ final float max;
+ if (mThumbPosition == THUMB_POSITION_INSIDE) {
+ final float halfThumbHeight = thumbImage.getHeight() / 2f;
+ min = trackImage.getTop() + halfThumbHeight;
+ max = trackImage.getBottom() - halfThumbHeight;
+ } else{
+ min = trackImage.getTop();
+ max = trackImage.getBottom();
+ }
+
+ mThumbOffset = min;
+ mThumbRange = max - min;
+ }
+
private void setState(int state) {
mList.removeCallbacks(mDeferHide);
@@ -1145,18 +1186,8 @@ class FastScroller {
* to place the thumb.
*/
private void setThumbPos(float position) {
- final Rect container = mContainerRect;
- final int top = container.top;
- final int bottom = container.bottom;
-
- final View trackImage = mTrackImage;
- final View thumbImage = mThumbImage;
- final float min = trackImage.getTop();
- final float max = trackImage.getBottom();
- final float offset = min;
- final float range = max - min;
- final float thumbMiddle = position * range + offset;
- thumbImage.setTranslationY(thumbMiddle - thumbImage.getHeight() / 2);
+ final float thumbMiddle = position * mThumbRange + mThumbOffset;
+ mThumbImage.setTranslationY(thumbMiddle - mThumbImage.getHeight() / 2f);
final View previewImage = mPreviewImage;
final float previewHalfHeight = previewImage.getHeight() / 2f;
@@ -1175,6 +1206,9 @@ class FastScroller {
}
// Center the preview on the thumb, constrained to the list bounds.
+ final Rect container = mContainerRect;
+ final int top = container.top;
+ final int bottom = container.bottom;
final float minP = top + previewHalfHeight;
final float maxP = bottom - previewHalfHeight;
final float previewMiddle = MathUtils.constrain(previewPos, minP, maxP);
@@ -1186,19 +1220,13 @@ class FastScroller {
}
private float getPosFromMotionEvent(float y) {
- final View trackImage = mTrackImage;
- final float min = trackImage.getTop();
- final float max = trackImage.getBottom();
- final float offset = min;
- final float range = max - min;
-
// If the list is the same height as the thumbnail or shorter,
// effectively disable scrolling.
- if (range <= 0) {
+ if (mThumbRange <= 0) {
return 0f;
}
- return MathUtils.constrain((y - offset) / range, 0f, 1f);
+ return MathUtils.constrain((y - mThumbOffset) / mThumbRange, 0f, 1f);
}
/**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9caa584..11439e4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9067,6 +9067,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
boolean selectAllText() {
+ // Need to hide insert point cursor controller before settings selection, otherwise insert
+ // point cursor controller obtains cursor update event and update cursor with cancelling
+ // selection.
+ if (mEditor != null) {
+ mEditor.hideInsertionPointCursorController();
+ }
final int length = mText.length();
Selection.setSelection((Spannable) mText, 0, length);
return length > 0;