summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/ApplicationPackageManager.java23
-rw-r--r--core/java/android/app/Notification.java18
-rw-r--r--core/java/android/app/admin/DeviceAdminInfo.java8
-rwxr-xr-xcore/java/android/app/admin/DevicePolicyManager.java42
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl4
-rw-r--r--core/java/android/appwidget/AppWidgetHostView.java7
-rw-r--r--core/java/android/content/pm/PackageManager.java64
-rw-r--r--core/java/android/hardware/Camera.java15
-rw-r--r--core/java/android/os/UserManager.java9
-rw-r--r--core/java/android/provider/MediaStore.java33
-rw-r--r--core/java/android/provider/Settings.java19
-rw-r--r--core/java/android/service/dreams/Dream.java286
-rw-r--r--core/java/android/view/Choreographer.java20
-rw-r--r--core/java/android/view/DisplayEventReceiver.java26
-rw-r--r--core/java/android/view/GLES20Canvas.java15
-rw-r--r--core/java/android/view/GLES20RenderLayer.java2
-rw-r--r--core/java/android/view/GLES20TextureLayer.java2
-rw-r--r--core/java/android/view/HardwareCanvas.java16
-rw-r--r--core/java/android/view/HardwareLayer.java2
-rw-r--r--core/java/android/view/HardwareRenderer.java34
-rw-r--r--core/java/android/view/View.java5
-rw-r--r--core/java/android/view/ViewRootImpl.java6
-rw-r--r--core/java/android/view/accessibility/AccessibilityManager.java60
-rw-r--r--core/java/android/view/accessibility/IAccessibilityManager.aidl12
-rw-r--r--core/java/android/webkit/WebViewClassic.java6
-rw-r--r--core/java/android/widget/ActivityChooserModel.java8
-rwxr-xr-xcore/java/android/widget/AppSecurityPermissions.java2
-rw-r--r--core/java/android/widget/CalendarView.java128
-rw-r--r--core/java/android/widget/DatePicker.java2
-rw-r--r--core/java/android/widget/NumberPicker.java71
-rw-r--r--core/java/android/widget/RemoteViews.java8
-rw-r--r--core/java/android/widget/TimePicker.java4
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java54
33 files changed, 792 insertions, 219 deletions
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 7870031..18503f6 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -42,10 +42,8 @@ import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.ManifestDigest;
-import android.content.pm.UserInfo;
import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
@@ -453,11 +451,17 @@ final class ApplicationPackageManager extends PackageManager {
@Override
public ResolveInfo resolveActivity(Intent intent, int flags) {
+ return resolveActivityAsUser(intent, flags, UserHandle.myUserId());
+ }
+
+ @Override
+ public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) {
try {
return mPM.resolveIntent(
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- flags, UserHandle.myUserId());
+ flags,
+ userId);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
@@ -466,12 +470,12 @@ final class ApplicationPackageManager extends PackageManager {
@Override
public List<ResolveInfo> queryIntentActivities(Intent intent,
int flags) {
- return queryIntentActivitiesForUser(intent, flags, UserHandle.myUserId());
+ return queryIntentActivitiesAsUser(intent, flags, UserHandle.myUserId());
}
/** @hide Same as above but for a specific user */
@Override
- public List<ResolveInfo> queryIntentActivitiesForUser(Intent intent,
+ public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,
int flags, int userId) {
try {
return mPM.queryIntentActivities(
@@ -551,19 +555,24 @@ final class ApplicationPackageManager extends PackageManager {
}
@Override
- public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
+ public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) {
try {
return mPM.queryIntentServices(
intent,
intent.resolveTypeIfNeeded(mContext.getContentResolver()),
flags,
- UserHandle.myUserId());
+ userId);
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
@Override
+ public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
+ return queryIntentServicesAsUser(intent, flags, UserHandle.myUserId());
+ }
+
+ @Override
public ProviderInfo resolveContentProvider(String name,
int flags) {
try {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 7896450..17c2c6b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -951,6 +951,7 @@ public class Notification implements Parcelable
private ArrayList<Action> mActions = new ArrayList<Action>(MAX_ACTION_BUTTONS);
private boolean mUseChronometer;
private Style mStyle;
+ private boolean mShowWhen = true;
/**
* Constructs a new Builder with the defaults:
@@ -982,8 +983,9 @@ public class Notification implements Parcelable
/**
* Add a timestamp pertaining to the notification (usually the time the event occurred).
+ * It will be shown in the notification content view by default; use
+ * {@link Builder#setShowWhen(boolean) setShowWhen} to control this.
*
-
* @see Notification#when
*/
public Builder setWhen(long when) {
@@ -992,6 +994,15 @@ public class Notification implements Parcelable
}
/**
+ * Control whether the timestamp set with {@link Builder#setWhen(long) setWhen} is shown
+ * in the content view.
+ */
+ public Builder setShowWhen(boolean show) {
+ mShowWhen = show;
+ return this;
+ }
+
+ /**
* Show the {@link Notification#when} field as a stopwatch.
*
* Instead of presenting <code>when</code> as a timestamp, the notification will show an
@@ -1467,7 +1478,7 @@ public class Notification implements Parcelable
contentView.setViewPadding(R.id.line1, 0, 0, 0, 0);
}
- if (mWhen != 0) {
+ if (mWhen != 0 && mShowWhen) {
if (mUseChronometer) {
contentView.setViewVisibility(R.id.chronometer, View.VISIBLE);
contentView.setLong(R.id.chronometer, "setBase",
@@ -1477,7 +1488,10 @@ public class Notification implements Parcelable
contentView.setViewVisibility(R.id.time, View.VISIBLE);
contentView.setLong(R.id.time, "setTime", mWhen);
}
+ } else {
+ contentView.setViewVisibility(R.id.time, View.GONE);
}
+
contentView.setViewVisibility(R.id.line3, showLine3 ? View.VISIBLE : View.GONE);
contentView.setViewVisibility(R.id.overflow_divider, showLine3 ? View.VISIBLE : View.GONE);
return contentView;
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index c8062ca..b351811 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -144,7 +144,7 @@ public final class DeviceAdminInfo implements Parcelable {
* <p>To control this policy, the device admin must have a "disable-keyguard-widgets"
* tag in the "uses-policies" section of its meta-data.
*/
- public static final int USES_POLICY_DISABLE_KEYGUARD_WIDGETS = 9;
+ public static final int USES_POLICY_DISABLE_KEYGUARD_FEATURES = 9;
/** @hide */
public static class PolicyInfo {
@@ -194,9 +194,9 @@ public final class DeviceAdminInfo implements Parcelable {
com.android.internal.R.string.policylab_disableCamera,
com.android.internal.R.string.policydesc_disableCamera));
sPoliciesDisplayOrder.add(new PolicyInfo(
- USES_POLICY_DISABLE_KEYGUARD_WIDGETS, "disable-keyguard-widgets",
- com.android.internal.R.string.policylab_disableKeyguardWidgets,
- com.android.internal.R.string.policydesc_disableKeyguardWidgets));
+ USES_POLICY_DISABLE_KEYGUARD_FEATURES, "disable-keyguard-features",
+ com.android.internal.R.string.policylab_disableKeyguardFeatures,
+ com.android.internal.R.string.policydesc_disableKeyguardFeatures));
for (int i=0; i<sPoliciesDisplayOrder.size(); i++) {
PolicyInfo pi = sPoliciesDisplayOrder.get(i);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 600d02a..6966793 100755
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1215,12 +1215,22 @@ public class DevicePolicyManager {
/**
* Widgets are enabled in keyguard
*/
- public static final int KEYGUARD_DISABLE_WIDGETS_NONE = 0;
+ public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0;
/**
* Disable all keyguard widgets
*/
- public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 0x7fffffff;
+ public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1 << 0;
+
+ /**
+ * Disable the camera on secure keyguard screens (e.g. PIN/Pattern/Password)
+ */
+ public static final int KEYGUARD_DISABLE_SECURE_CAMERA = 1 << 1;
+
+ /**
+ * Disable all current and future keyguard customizations
+ */
+ public static final int KEYGUARD_DISABLE_FEATURES_ALL = 0x7fffffff;
/**
* Called by an application that is administering the device to
@@ -1362,22 +1372,22 @@ public class DevicePolicyManager {
}
/**
- * Called by an application that is administering the device to disable adding widgets to
- * keyguard. After setting this, keyguard widgets will be disabled according to the state
- * provided.
+ * Called by an application that is administering the device to disable keyguard customizations,
+ * such as widgets. After setting this, keyguard features will be disabled according to the
+ * provided feature list.
*
* <p>The calling device admin must have requested
- * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_WIDGETS} to be able to call
+ * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call
* this method; if it has not, a security exception will be thrown.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param which {@link DevicePolicyManager#KEYGUARD_DISABLE_WIDGETS_ALL} or
- * {@link DevicePolicyManager#KEYGUARD_DISABLE_WIDGETS_NONE} (the default).
+ * {@link DevicePolicyManager#KEYGUARD_DISABLE_FEATURES_NONE} (the default).
*/
- public void setKeyguardWidgetsDisabled(ComponentName admin, int which) {
+ public void setKeyguardDisabledFeatures(ComponentName admin, int which) {
if (mService != null) {
try {
- mService.setKeyguardWidgetsDisabled(admin, which, UserHandle.myUserId());
+ mService.setKeyguardDisabledFeatures(admin, which, UserHandle.myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -1385,25 +1395,25 @@ public class DevicePolicyManager {
}
/**
- * Determine whether or not widgets have been disabled in keyguard either by the current
+ * Determine whether or not features have been disabled in keyguard either by the current
* admin, if specified, or all admins.
* @param admin The name of the admin component to check, or null to check if any admins
- * have disabled widgets in keyguard.
+ * have disabled features in keyguard.
*/
- public int getKeyguardWidgetsDisabled(ComponentName admin) {
- return getKeyguardWidgetsDisabled(admin, UserHandle.myUserId());
+ public int getKeyguardDisabledFeatures(ComponentName admin) {
+ return getKeyguardDisabledFeatures(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getKeyguardWidgetsDisabled(ComponentName admin, int userHandle) {
+ public int getKeyguardDisabledFeatures(ComponentName admin, int userHandle) {
if (mService != null) {
try {
- return mService.getKeyguardWidgetsDisabled(admin, userHandle);
+ return mService.getKeyguardDisabledFeatures(admin, userHandle);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
}
- return KEYGUARD_DISABLE_WIDGETS_NONE;
+ return KEYGUARD_DISABLE_FEATURES_NONE;
}
/**
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index bdfb177..e061ab3 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -82,8 +82,8 @@ interface IDevicePolicyManager {
void setCameraDisabled(in ComponentName who, boolean disabled, int userHandle);
boolean getCameraDisabled(in ComponentName who, int userHandle);
- void setKeyguardWidgetsDisabled(in ComponentName who, int which, int userHandle);
- int getKeyguardWidgetsDisabled(in ComponentName who, int userHandle);
+ void setKeyguardDisabledFeatures(in ComponentName who, int which, int userHandle);
+ int getKeyguardDisabledFeatures(in ComponentName who, int userHandle);
void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing, int userHandle);
boolean isAdminActive(in ComponentName policyReceiver, int userHandle);
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index c86826f..f258f17 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -226,7 +226,12 @@ public class AppWidgetHostView extends FrameLayout {
if (jail == null) jail = new ParcelableSparseArray();
- super.dispatchRestoreInstanceState(jail);
+ try {
+ super.dispatchRestoreInstanceState(jail);
+ } catch (Exception e) {
+ Log.e(TAG, "failed to restoreInstanceState for widget id: " + mAppWidgetId + ", "
+ + (mInfo == null ? "null" : mInfo.provider), e);
+ }
}
/**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index fd488ae..291726a 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -835,6 +835,14 @@ public abstract class PackageManager {
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device has at least one camera pointing in
+ * some direction.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_CAMERA_ANY = "android.hardware.camera.any";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device's camera supports flash.
*/
@SdkConstant(SdkConstantType.FEATURE)
@@ -1797,6 +1805,39 @@ public abstract class PackageManager {
public abstract ResolveInfo resolveActivity(Intent intent, int flags);
/**
+ * Determine the best action to perform for a given Intent for a given user. This
+ * is how {@link Intent#resolveActivity} finds an activity if a class has not
+ * been explicitly specified.
+ *
+ * <p><em>Note:</em> if using an implicit Intent (without an explicit ComponentName
+ * specified), be sure to consider whether to set the {@link #MATCH_DEFAULT_ONLY}
+ * only flag. You need to do so to resolve the activity in the same way
+ * that {@link android.content.Context#startActivity(Intent)} and
+ * {@link android.content.Intent#resolveActivity(PackageManager)
+ * Intent.resolveActivity(PackageManager)} do.</p>
+ *
+ * @param intent An intent containing all of the desired specification
+ * (action, data, type, category, and/or component).
+ * @param flags Additional option flags. The most important is
+ * {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
+ * those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
+ * @param userId The user id.
+ *
+ * @return Returns a ResolveInfo containing the final activity intent that
+ * was determined to be the best action. Returns null if no
+ * matching activity was found. If multiple matching activities are
+ * found and there is no default set, returns a ResolveInfo
+ * containing something else, such as the activity resolver.
+ *
+ * @see #MATCH_DEFAULT_ONLY
+ * @see #GET_INTENT_FILTERS
+ * @see #GET_RESOLVED_FILTER
+ *
+ * @hide
+ */
+ public abstract ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId);
+
+ /**
* Retrieve all activities that can be performed for the given intent.
*
* @param intent The desired intent as per resolveActivity().
@@ -1836,7 +1877,7 @@ public abstract class PackageManager {
* @see #GET_RESOLVED_FILTER
* @hide
*/
- public abstract List<ResolveInfo> queryIntentActivitiesForUser(Intent intent,
+ public abstract List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,
int flags, int userId);
@@ -1944,6 +1985,27 @@ public abstract class PackageManager {
int flags);
/**
+ * Retrieve all services that can match the given intent for a given user.
+ *
+ * @param intent The desired intent as per resolveService().
+ * @param flags Additional option flags.
+ * @param userId The user id.
+ *
+ * @return A List&lt;ResolveInfo&gt; containing one entry for each matching
+ * ServiceInfo. These are ordered from best to worst match -- that
+ * is, the first item in the list is what is returned by
+ * resolveService(). If there are no matching services, an empty
+ * list is returned.
+ *
+ * @see #GET_INTENT_FILTERS
+ * @see #GET_RESOLVED_FILTER
+ *
+ * @hide
+ */
+ public abstract List<ResolveInfo> queryIntentServicesAsUser(Intent intent,
+ int flags, int userId);
+
+ /**
* Find a single content provider by its base path name.
*
* @param name The name of the provider to find.
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 7b3a8af..375d788 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -233,6 +233,21 @@ public class Camera {
* @see Parameters#setJpegThumbnailSize(int, int)
*/
public int orientation;
+
+ /**
+ * <p>Whether the shutter sound can be disabled.</p>
+ *
+ * <p>On some devices, the camera shutter sound cannot be turned off
+ * through {@link #enableShutterSound enableShutterSound}. This field
+ * can be used to determine whether a call to disable the shutter sound
+ * will succeed.</p>
+ *
+ * <p>If this field is set to true, then a call of
+ * {@code enableShutterSound(false)} will be successful. If set to
+ * false, then that call will fail, and the shutter sound will be played
+ * when {@link Camera#takePicture takePicture} is called.</p>
+ */
+ public boolean canDisableShutterSound;
};
/**
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 2a5c1aa..96c96d7 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -72,6 +72,15 @@ public class UserManager {
}
}
+ /**
+ * Used to determine whether the user making this call is subject to
+ * teleportations.
+ * @return whether the user making this call is a goat
+ */
+ public boolean isUserAGoat() {
+ return false;
+ }
+
/**
* Returns the UserInfo object describing a specific user.
* Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index cfa5479..0e7ab52 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -122,6 +122,38 @@ public final class MediaStore {
"android.media.action.MEDIA_PLAY_FROM_SEARCH";
/**
+ * An intent to perform a search for readable media and automatically play content from the
+ * result when possible. This can be fired, for example, by the result of a voice recognition
+ * command to read a book or magazine.
+ * <p>
+ * Contains the {@link android.app.SearchManager#QUERY} extra, which is a string that can
+ * contain any type of unstructured text search, like the name of a book or magazine, an author
+ * a genre, a publisher, or any combination of these.
+ * <p>
+ * Because this intent includes an open-ended unstructured search string, it makes the most
+ * sense for apps that can support large-scale search of text media, such as services connected
+ * to an online database of books and/or magazines which can be read on the device.
+ */
+ public static final String INTENT_ACTION_TEXT_OPEN_FROM_SEARCH =
+ "android.media.action.TEXT_OPEN_FROM_SEARCH";
+
+ /**
+ * An intent to perform a search for video media and automatically play content from the
+ * result when possible. This can be fired, for example, by the result of a voice recognition
+ * command to play movies.
+ * <p>
+ * Contains the {@link android.app.SearchManager#QUERY} extra, which is a string that can
+ * contain any type of unstructured video search, like the name of a movie, one or more actors,
+ * a genre, or any combination of these.
+ * <p>
+ * Because this intent includes an open-ended unstructured search string, it makes the most
+ * sense for apps that can support large-scale search of video, such as services connected to an
+ * online database of videos which can be streamed and played on the device.
+ */
+ public static final String INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH =
+ "android.media.action.VIDEO_PLAY_FROM_SEARCH";
+
+ /**
* The name of the Intent-extra used to define the artist
*/
public static final String EXTRA_MEDIA_ARTIST = "android.intent.extra.artist";
@@ -223,7 +255,6 @@ public final class MediaStore {
*
* @see #ACTION_IMAGE_CAPTURE
* @see #EXTRA_OUTPUT
- * @hide
*/
public static final String ACTION_IMAGE_CAPTURE_SECURE =
"android.media.action.IMAGE_CAPTURE_SECURE";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 66738a1..7864302 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5334,26 +5334,35 @@ public final class Settings {
* review apps prior to installation.
* 1 = request apps to be verified prior to installation, if a verifier exists.
* 0 = do not verify apps before installation
- * {@hide}
+ * @hide
*/
public static final String PACKAGE_VERIFIER_ENABLE = "package_verifier_enable";
/** Timeout for package verification.
- * {@hide} */
+ * @hide */
public static final String PACKAGE_VERIFIER_TIMEOUT = "verifier_timeout";
/** Default response code for package verification.
- * {@hide} */
+ * @hide */
public static final String PACKAGE_VERIFIER_DEFAULT_RESPONSE = "verifier_default_response";
- /** Show package verification setting in the Settings app.
+ /**
+ * Show package verification setting in the Settings app.
* 1 = show (default)
* 0 = hide
- * {@hide}
+ * @hide
*/
public static final String PACKAGE_VERIFIER_SETTING_VISIBLE = "verifier_setting_visible";
/**
+ * Run package verificaiton on apps installed through ADB/ADT/USB
+ * 1 = perform package verification on ADB installs (default)
+ * 0 = bypass package verification on ADB installs
+ * @hide
+ */
+ public static final String PACKAGE_VERIFIER_INCLUDE_ADB = "verifier_verify_adb_installs";
+
+ /**
* The interval in milliseconds at which to check packet counts on the
* mobile data interface when screen is on, to detect possible data
* connection problems.
diff --git a/core/java/android/service/dreams/Dream.java b/core/java/android/service/dreams/Dream.java
index 4a23d39..dedfb0c 100644
--- a/core/java/android/service/dreams/Dream.java
+++ b/core/java/android/service/dreams/Dream.java
@@ -44,22 +44,47 @@ import com.android.internal.policy.PolicyManager;
* <p>Dreams are interactive screensavers launched when a charging device is idle, or docked in a
* desk dock. Dreams provide another modality for apps to express themselves, tailored for
* an exhibition/lean-back experience.</p>
+ *
+ * <p>Dreams should be declared in the manifest as follows:</p>
+ * <pre>
+ * {@code
+ * <service
+ * android:name=".MyDream"
+ * android:exported="true"
+ * android:icon="@drawable/my_icon"
+ * android:label="@string/my_dream_label" >
+ *
+ * <intent-filter>
+ * <action android:name="android.intent.action.MAIN" />
+ * <category android:name="android.intent.category.DREAM" />
+ * </intent-filter>
+ *
+ * <!-- Point to configuration activity for this dream (optional) -->
+ * <meta-data
+ * android:name="android.service.dreams.config_activity"
+ * android:value="com.example.mypackage/com.example.mypackage.MyDreamSettingsActivity" />
+ * </service>
+ * }
+ * </pre>
*/
public class Dream extends Service implements Window.Callback {
private final static boolean DEBUG = true;
private final String TAG = Dream.class.getSimpleName() + "[" + getClass().getSimpleName() + "]";
/**
- * The {@link Intent} that must be declared as handled by the service.
- * To be supported, the service must also require the
- * {@link android.Manifest.permission#BIND_WALLPAPER} permission so
- * that other applications can not abuse it.
+ * Used with {@link Intent#ACTION_MAIN} to declare the necessary intent-filter for a dream.
+ *
+ * @see Dream
*/
- @SdkConstant(SdkConstantType.SERVICE_ACTION)
- public static final String SERVICE_INTERFACE =
- "android.service.dreams.Dream";
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_DREAM =
+ "android.intent.category.DREAM";
- /** Service meta-data key for declaring an optional configuration activity. */
+ /**
+ * Service meta-data key for declaring an optional configuration activity.
+ *
+ * @see Dream
+ * */
public static final String METADATA_NAME_CONFIG_ACTIVITY =
"android.service.dreams.config_activity";
@@ -86,10 +111,14 @@ public class Dream extends Service implements Window.Callback {
private Window mWindow;
private WindowManager mWindowManager;
private IDreamManager mSandman;
- private boolean mInteractive;
+ private boolean mInteractive = false;
+ private boolean mLowProfile = true;
+ private boolean mFullscreen = false;
+ private boolean mScreenBright = false;
private boolean mFinished;
// begin Window.Callback methods
+ /** {@inheritDoc} */
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
// TODO: create more flexible version of mInteractive that allows use of KEYCODE_BACK
@@ -105,6 +134,7 @@ public class Dream extends Service implements Window.Callback {
return mWindow.superDispatchKeyEvent(event);
}
+ /** {@inheritDoc} */
@Override
public boolean dispatchKeyShortcutEvent(KeyEvent event) {
if (!mInteractive) {
@@ -115,6 +145,7 @@ public class Dream extends Service implements Window.Callback {
return mWindow.superDispatchKeyShortcutEvent(event);
}
+ /** {@inheritDoc} */
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
// TODO: create more flexible version of mInteractive that allows clicks
@@ -127,6 +158,7 @@ public class Dream extends Service implements Window.Callback {
return mWindow.superDispatchTouchEvent(event);
}
+ /** {@inheritDoc} */
@Override
public boolean dispatchTrackballEvent(MotionEvent event) {
if (!mInteractive) {
@@ -137,6 +169,7 @@ public class Dream extends Service implements Window.Callback {
return mWindow.superDispatchTrackballEvent(event);
}
+ /** {@inheritDoc} */
@Override
public boolean dispatchGenericMotionEvent(MotionEvent event) {
if (!mInteractive) {
@@ -147,86 +180,112 @@ public class Dream extends Service implements Window.Callback {
return mWindow.superDispatchGenericMotionEvent(event);
}
+ /** {@inheritDoc} */
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
return false;
}
+ /** {@inheritDoc} */
@Override
public View onCreatePanelView(int featureId) {
return null;
}
+ /** {@inheritDoc} */
@Override
public boolean onCreatePanelMenu(int featureId, Menu menu) {
return false;
}
+ /** {@inheritDoc} */
@Override
public boolean onPreparePanel(int featureId, View view, Menu menu) {
return false;
}
+ /** {@inheritDoc} */
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
return false;
}
+ /** {@inheritDoc} */
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
return false;
}
+ /** {@inheritDoc} */
@Override
public void onWindowAttributesChanged(LayoutParams attrs) {
-
}
+ /** {@inheritDoc} */
@Override
public void onContentChanged() {
-
}
+ /** {@inheritDoc} */
@Override
public void onWindowFocusChanged(boolean hasFocus) {
-
}
+ /** {@inheritDoc} */
@Override
public void onAttachedToWindow() {
}
+ /** {@inheritDoc} */
@Override
public void onDetachedFromWindow() {
}
+ /** {@inheritDoc} */
@Override
public void onPanelClosed(int featureId, Menu menu) {
}
+ /** {@inheritDoc} */
@Override
public boolean onSearchRequested() {
return false;
}
+ /** {@inheritDoc} */
@Override
public ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback callback) {
return null;
}
+ /** {@inheritDoc} */
@Override
public void onActionModeStarted(ActionMode mode) {
}
+ /** {@inheritDoc} */
@Override
public void onActionModeFinished(ActionMode mode) {
}
// end Window.Callback methods
+ // begin public api
+ /**
+ * Retrieves the current {@link android.view.WindowManager} for the dream.
+ * Behaves similarly to {@link android.app.Activity#getWindowManager()}.
+ *
+ * @return The current window manager, or null if the dream is not started.
+ */
public WindowManager getWindowManager() {
return mWindowManager;
}
+ /**
+ * Retrieves the current {@link android.view.Window} for the dream.
+ * Behaves similarly to {@link android.app.Activity#getWindow()}.
+ *
+ * @return The current window, or null if the dream is not started.
+ */
public Window getWindow() {
return mWindow;
}
@@ -235,6 +294,8 @@ public class Dream extends Service implements Window.Callback {
* Inflates a layout resource and set it to be the content view for this Dream.
* Behaves similarly to {@link android.app.Activity#setContentView(int)}.
*
+ * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
+ *
* @param layoutResID Resource ID to be inflated.
*
* @see #setContentView(android.view.View)
@@ -248,7 +309,8 @@ public class Dream extends Service implements Window.Callback {
* Sets a view to be the content view for this Dream.
* Behaves similarly to {@link android.app.Activity#setContentView(android.view.View)},
* including using {@link ViewGroup.LayoutParams#MATCH_PARENT} as the layout height and width of the view.
- *
+ *
+ * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
* @param view The desired content to display.
*
* @see #setContentView(int)
@@ -263,6 +325,8 @@ public class Dream extends Service implements Window.Callback {
* Behaves similarly to
* {@link android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}.
*
+ * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
+ *
* @param view The desired content to display.
* @param params Layout parameters for the view.
*
@@ -275,7 +339,9 @@ public class Dream extends Service implements Window.Callback {
/**
* Adds a view to the Dream's window, leaving other content views in place.
- *
+ *
+ * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
+ *
* @param view The desired content to display.
* @param params Layout parameters for the view.
*/
@@ -284,6 +350,25 @@ public class Dream extends Service implements Window.Callback {
}
/**
+ * Finds a view that was identified by the id attribute from the XML that
+ * was processed in {@link #onCreate}.
+ *
+ * <p>Note: Requires a window, do not call before {@link #onAttachedToWindow()}</p>
+ *
+ * @return The view if found or null otherwise.
+ */
+ public View findViewById(int id) {
+ return getWindow().findViewById(id);
+ }
+
+ /** FIXME remove once platform dreams are updated */
+ @Deprecated
+ protected void lightsOut() {
+ setLowProfile(true);
+ setFullscreen(true);
+ }
+
+ /**
* Marks this dream as interactive to receive input events.
*
* <p>Non-interactive dreams (default) will dismiss on the first input event.</p>
@@ -297,36 +382,79 @@ public class Dream extends Service implements Window.Callback {
}
/**
- * Returns whether or not this dream is interactive.
+ * Returns whether or not this dream is interactive. Defaults to false.
+ *
+ * @see #setInteractive(boolean)
*/
public boolean isInteractive() {
return mInteractive;
}
- /** Convenience method for setting View.SYSTEM_UI_FLAG_LOW_PROFILE on the content view. */
- protected void lightsOut() {
- // turn the lights down low
- final View v = mWindow.getDecorView();
- if (v != null) {
- v.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
- | View.SYSTEM_UI_FLAG_FULLSCREEN);
- }
+ /**
+ * Sets View.SYSTEM_UI_FLAG_LOW_PROFILE on the content view.
+ *
+ * @param lowProfile True to set View.SYSTEM_UI_FLAG_LOW_PROFILE
+ */
+ public void setLowProfile(boolean lowProfile) {
+ mLowProfile = lowProfile;
+ int flag = View.SYSTEM_UI_FLAG_LOW_PROFILE;
+ applySystemUiVisibilityFlags(mLowProfile ? flag : 0, flag);
}
/**
- * Finds a view that was identified by the id attribute from the XML that
- * was processed in {@link #onCreate}.
+ * Returns whether or not this dream is in low profile mode. Defaults to true.
*
- * @return The view if found or null otherwise.
+ * @see #setLowProfile(boolean)
*/
- public View findViewById(int id) {
- return getWindow().findViewById(id);
+ public boolean isLowProfile() {
+ return getSystemUiVisibilityFlagValue(View.SYSTEM_UI_FLAG_LOW_PROFILE, mLowProfile);
+ }
+
+ /**
+ * Sets View.SYSTEM_UI_FLAG_FULLSCREEN on the content view.
+ *
+ * @param fullscreen True to set View.SYSTEM_UI_FLAG_FULLSCREEN
+ */
+ public void setFullscreen(boolean fullscreen) {
+ mFullscreen = fullscreen;
+ int flag = View.SYSTEM_UI_FLAG_FULLSCREEN;
+ applySystemUiVisibilityFlags(mFullscreen ? flag : 0, flag);
+ }
+
+ /**
+ * Returns whether or not this dream is in fullscreen mode. Defaults to false.
+ *
+ * @see #setFullscreen(boolean)
+ */
+ public boolean isFullscreen() {
+ return getSystemUiVisibilityFlagValue(View.SYSTEM_UI_FLAG_FULLSCREEN, mFullscreen);
+ }
+
+ /**
+ * Marks this dream as keeping the screen bright while dreaming.
+ *
+ * @param screenBright True to keep the screen bright while dreaming.
+ */
+ public void setScreenBright(boolean screenBright) {
+ mScreenBright = screenBright;
+ int flag = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+ applyWindowFlags(mScreenBright ? flag : 0, flag);
+ }
+
+ /**
+ * Returns whether or not this dream keeps the screen bright while dreaming. Defaults to false,
+ * allowing the screen to dim if necessary.
+ *
+ * @see #setScreenBright(boolean)
+ */
+ public boolean isScreenBright() {
+ return getWindowFlagValue(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, mScreenBright);
}
/**
* Called when this Dream is constructed. Place your initialization here.
*
- * Subclasses must call through to the superclass implementation.
+ * <p>Subclasses must call through to the superclass implementation.</p>
*/
@Override
public void onCreate() {
@@ -336,23 +464,51 @@ public class Dream extends Service implements Window.Callback {
}
/**
- * Called when this Dream is started.
+ * Called when this Dream is started. The window is created and visible at this point.
*/
public void onStart() {
+ if (DEBUG) Slog.v(TAG, "onStart()");
// hook for subclasses
- Slog.v(TAG, "called Dream.onStart()");
}
- private void loadSandman() {
- mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams"));
+ /** {@inheritDoc} */
+ @Override
+ public final IBinder onBind(Intent intent) {
+ if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
+ return new DreamServiceWrapper();
}
/**
- * Creates a new dream window, attaches the current content view, and shows it.
- *
- * @param windowToken Binder to attach to the window to allow access to the correct window type.
- * @hide
+ * Stops the dream, detaches from the window, and wakes up.
+ *
+ * <p>Subclasses must call through to the superclass implementation.</p>
+ *
+ * <p>After this method is called, the service will be stopped.</p>
*/
+ public void finish() {
+ if (DEBUG) Slog.v(TAG, "finish()");
+ finishInternal();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void onDestroy() {
+ if (DEBUG) Slog.v(TAG, "onDestroy()");
+ super.onDestroy();
+
+ if (DEBUG) Slog.v(TAG, "Removing window");
+ try {
+ mWindowManager.removeView(mWindow.getDecorView());
+ } catch (Throwable t) {
+ Slog.w(TAG, "Crashed removing window view", t);
+ }
+ }
+ // end public api
+
+ private void loadSandman() {
+ mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams"));
+ }
+
private final void attach(IBinder windowToken) {
if (DEBUG) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId());
@@ -375,7 +531,8 @@ public class Dream extends Service implements Window.Callback {
lp.windowAnimations = com.android.internal.R.style.Animation_Dream;
lp.flags |= ( WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
- | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
+ | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
+ | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0)
);
mWindow.setAttributes(lp);
@@ -389,8 +546,11 @@ public class Dream extends Service implements Window.Callback {
@Override
public void run() {
if (DEBUG) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId());
-
try {
+ applySystemUiVisibilityFlags(
+ (mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0)
+ | (mFullscreen ? View.SYSTEM_UI_FLAG_FULLSCREEN : 0),
+ View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN);
getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
} catch (Throwable t) {
Slog.w("Crashed adding window view", t);
@@ -424,18 +584,6 @@ public class Dream extends Service implements Window.Callback {
}
}
- /**
- * Stops the dream, detaches from the window, and wakes up.
- *
- * Subclasses must call through to the superclass implementation.
- *
- * <p>After this method is called, the service will be stopped.</p>
- */
- public void finish() {
- if (DEBUG) Slog.v(TAG, "finish()");
- finishInternal();
- }
-
private void finishInternal() {
if (DEBUG) Slog.v(TAG, "finishInternal() mFinished = " + mFinished);
if (mFinished) return;
@@ -454,23 +602,33 @@ public class Dream extends Service implements Window.Callback {
}
}
- @Override
- public void onDestroy() {
- if (DEBUG) Slog.v(TAG, "onDestroy()");
- super.onDestroy();
+ private boolean getWindowFlagValue(int flag, boolean defaultValue) {
+ return mWindow == null ? defaultValue : (mWindow.getAttributes().flags & flag) != 0;
+ }
- if (DEBUG) Slog.v(TAG, "Removing window");
- try {
- mWindowManager.removeView(mWindow.getDecorView());
- } catch (Throwable t) {
- Slog.w(TAG, "Crashed removing window view", t);
+ private void applyWindowFlags(int flags, int mask) {
+ if (mWindow != null) {
+ WindowManager.LayoutParams lp = mWindow.getAttributes();
+ lp.flags = applyFlags(lp.flags, flags, mask);
+ mWindow.setAttributes(lp);
+ mWindowManager.updateViewLayout(mWindow.getDecorView(), lp);
}
}
- @Override
- public final IBinder onBind(Intent intent) {
- if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
- return new DreamServiceWrapper();
+ private boolean getSystemUiVisibilityFlagValue(int flag, boolean defaultValue) {
+ View v = mWindow == null ? null : mWindow.getDecorView();
+ return v == null ? defaultValue : (v.getSystemUiVisibility() & flag) != 0;
+ }
+
+ private void applySystemUiVisibilityFlags(int flags, int mask) {
+ View v = mWindow == null ? null : mWindow.getDecorView();
+ if (v != null) {
+ v.setSystemUiVisibility(applyFlags(v.getSystemUiVisibility(), flags, mask));
+ }
+ }
+
+ private int applyFlags(int oldFlags, int flags, int mask) {
+ return (oldFlags&~mask) | (flags&mask);
}
private class DreamServiceWrapper extends IDreamService.Stub {
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 6848606..b661748 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -16,7 +16,6 @@
package android.view;
-import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Handler;
import android.os.Looper;
@@ -685,7 +684,24 @@ public final class Choreographer {
}
@Override
- public void onVsync(long timestampNanos, int frame) {
+ public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
+ // Ignore vsync from secondary display.
+ // This can be problematic because the call to scheduleVsync() is a one-shot.
+ // We need to ensure that we will still receive the vsync from the primary
+ // display which is the one we really care about. Ideally we should schedule
+ // vsync for a particular display.
+ // At this time Surface Flinger won't send us vsyncs for secondary displays
+ // but that could change in the future so let's log a message to help us remember
+ // that we need to fix this.
+ if (builtInDisplayId != Surface.BUILT_IN_DISPLAY_ID_MAIN) {
+ Log.d(TAG, "Received vsync from secondary display, but we don't support "
+ + "this case yet. Choreographer needs a way to explicitly request "
+ + "vsync for a specific display to ensure it doesn't lose track "
+ + "of its scheduled vsync.");
+ scheduleVsync();
+ return;
+ }
+
// Post the vsync event to the Handler.
// The idea is to prevent incoming vsync events from completely starving
// the message queue. If there are no messages in the queue with timestamps
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index 0b138c2..a919ffc 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -101,9 +101,23 @@ public abstract class DisplayEventReceiver {
*
* @param timestampNanos The timestamp of the pulse, in the {@link System#nanoTime()}
* timebase.
+ * @param builtInDisplayId The surface flinger built-in display id such as
+ * {@link Surface#BUILT_IN_DISPLAY_ID_MAIN}.
* @param frame The frame number. Increases by one for each vertical sync interval.
*/
- public void onVsync(long timestampNanos, int frame) {
+ public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
+ }
+
+ /**
+ * Called when a display hotplug event is received.
+ *
+ * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
+ * timebase.
+ * @param builtInDisplayId The surface flinger built-in display id such as
+ * {@link Surface#BUILT_IN_DISPLAY_ID_HDMI}.
+ * @param connected True if the display is connected, false if it disconnected.
+ */
+ public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
}
/**
@@ -121,7 +135,13 @@ public abstract class DisplayEventReceiver {
// Called from native code.
@SuppressWarnings("unused")
- private void dispatchVsync(long timestampNanos, int frame) {
- onVsync(timestampNanos, frame);
+ private void dispatchVsync(long timestampNanos, int builtInDisplayId, int frame) {
+ onVsync(timestampNanos, builtInDisplayId, frame);
+ }
+
+ // Called from native code.
+ @SuppressWarnings("unused")
+ private void dispatchHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
+ onHotplug(timestampNanos, builtInDisplayId, connected);
}
}
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 032ff7b..c703aaf 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -147,7 +147,17 @@ class GLES20Canvas extends HardwareCanvas {
///////////////////////////////////////////////////////////////////////////
// Hardware layers
///////////////////////////////////////////////////////////////////////////
-
+
+ @Override
+ void pushLayerUpdate(HardwareLayer layer) {
+ nPushLayerUpdate(mRenderer, ((GLES20RenderLayer) layer).mLayer);
+ }
+
+ @Override
+ void clearLayerUpdates() {
+ nClearLayerUpdates(mRenderer);
+ }
+
static native int nCreateTextureLayer(boolean opaque, int[] layerInfo);
static native int nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo);
static native boolean nResizeLayer(int layerId, int width, int height, int[] layerInfo);
@@ -163,6 +173,9 @@ class GLES20Canvas extends HardwareCanvas {
int left, int top, int right, int bottom);
static native boolean nCopyLayer(int layerId, int bitmap);
+ private static native void nClearLayerUpdates(int renderer);
+ private static native void nPushLayerUpdate(int renderer, int layer);
+
///////////////////////////////////////////////////////////////////////////
// Canvas management
///////////////////////////////////////////////////////////////////////////
diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java
index fcfc8e1..44d4719 100644
--- a/core/java/android/view/GLES20RenderLayer.java
+++ b/core/java/android/view/GLES20RenderLayer.java
@@ -110,7 +110,7 @@ class GLES20RenderLayer extends GLES20Layer {
}
@Override
- void redraw(DisplayList displayList, Rect dirtyRect) {
+ void redrawLater(DisplayList displayList, Rect dirtyRect) {
GLES20Canvas.nUpdateRenderLayer(mLayer, mCanvas.getRenderer(),
((GLES20DisplayList) displayList).getNativeDisplayList(),
dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom);
diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java
index b0ee2aa..797c734 100644
--- a/core/java/android/view/GLES20TextureLayer.java
+++ b/core/java/android/view/GLES20TextureLayer.java
@@ -98,6 +98,6 @@ class GLES20TextureLayer extends GLES20Layer {
}
@Override
- void redraw(DisplayList displayList, Rect dirtyRect) {
+ void redrawLater(DisplayList displayList, Rect dirtyRect) {
}
}
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index 777552a..eeae3ed 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -132,4 +132,20 @@ public abstract class HardwareCanvas extends Canvas {
* @see #detachFunctor(int)
*/
abstract void attachFunctor(int functor);
+
+ /**
+ * Indicates that the specified layer must be updated as soon as possible.
+ *
+ * @param layer The layer to update
+ *
+ * @see #clearLayerUpdates()
+ */
+ abstract void pushLayerUpdate(HardwareLayer layer);
+
+ /**
+ * Removes all enqueued layer updates.
+ *
+ * @see #pushLayerUpdate(HardwareLayer)
+ */
+ abstract void clearLayerUpdates();
}
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index d798e73..d6868ca 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -203,5 +203,5 @@ abstract class HardwareLayer {
* execute in this layer
* @param dirtyRect The dirty region of the layer that needs to be redrawn
*/
- abstract void redraw(DisplayList displayList, Rect dirtyRect);
+ abstract void redrawLater(DisplayList displayList, Rect dirtyRect);
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index ef5dc56..bafab21 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -149,6 +149,17 @@ public abstract class HardwareRenderer {
"debug.hwui.show_layers_updates";
/**
+ * Turn on to show overdraw level.
+ *
+ * Possible values:
+ * "true", to enable overdraw debugging
+ * "false", to disable overdraw debugging
+ *
+ * @hide
+ */
+ public static final String DEBUG_SHOW_OVERDRAW_PROPERTY = "debug.hwui.show_overdraw";
+
+ /**
* A process can set this flag to false to prevent the use of hardware
* rendering.
*
@@ -370,6 +381,14 @@ public abstract class HardwareRenderer {
private static native void nDisableVsync();
/**
+ * Indicates that the specified hardware layer needs to be updated
+ * as soon as possible.
+ *
+ * @param layer The hardware layer that needs an update
+ */
+ abstract void pushLayerUpdate(HardwareLayer layer);
+
+ /**
* Interface used to receive callbacks whenever a view is drawn by
* a hardware renderer instance.
*/
@@ -641,6 +660,7 @@ public abstract class HardwareRenderer {
int mProfileCurrentFrame = -PROFILE_FRAME_DATA_COUNT;
final boolean mDebugDirtyRegions;
+ final boolean mShowOverdraw;
final int mGlVersion;
final boolean mTranslucent;
@@ -690,6 +710,9 @@ public abstract class HardwareRenderer {
if (mDebugDirtyRegions) {
Log.d(LOG_TAG, "Debugging dirty regions");
}
+
+ mShowOverdraw = SystemProperties.getBoolean(
+ HardwareRenderer.DEBUG_SHOW_OVERDRAW_PROPERTY, false);
}
@Override
@@ -1154,8 +1177,9 @@ public abstract class HardwareRenderer {
getDisplayListStartTime = System.nanoTime();
}
- DisplayList displayList;
+ canvas.clearLayerUpdates();
+ DisplayList displayList;
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
try {
displayList = view.getDisplayList();
@@ -1405,7 +1429,8 @@ public abstract class HardwareRenderer {
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 0,
- EGL_STENCIL_SIZE, GLES20Canvas.getStencilSize(),
+ // TODO: Find a better way to choose the stencil size
+ EGL_STENCIL_SIZE, mShowOverdraw ? GLES20Canvas.getStencilSize() : 0,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT |
(dirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
EGL_NONE
@@ -1452,6 +1477,11 @@ public abstract class HardwareRenderer {
}
@Override
+ void pushLayerUpdate(HardwareLayer layer) {
+ mGlCanvas.pushLayerUpdate(layer);
+ }
+
+ @Override
public DisplayList createDisplayList(String name) {
return new GLES20DisplayList(name);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 13de538..31bbc6a 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12286,9 +12286,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (!mHardwareLayer.isValid()) {
return null;
}
+
mHardwareLayer.setLayerPaint(mLayerPaint);
+ mHardwareLayer.redrawLater(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
+ ViewRootImpl viewRoot = getViewRootImpl();
+ if (viewRoot != null) viewRoot.pushHardwareLayerUpdate(mHardwareLayer);
- mHardwareLayer.redraw(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
mLocalDirtyRect.setEmpty();
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 27fd374..6bb8697 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -653,6 +653,12 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ void pushHardwareLayerUpdate(HardwareLayer layer) {
+ if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
+ mAttachInfo.mHardwareRenderer.pushLayerUpdate(layer);
+ }
+ }
+
public boolean attachFunctor(int functor) {
//noinspection SimplifiableIfStatement
if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 77fd12a..732699b 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -27,6 +27,7 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.util.Log;
import android.view.IWindow;
import android.view.View;
@@ -79,6 +80,8 @@ public final class AccessibilityManager {
final IAccessibilityManager mService;
+ final int mUserId;
+
final Handler mHandler;
boolean mIsEnabled;
@@ -129,35 +132,72 @@ public final class AccessibilityManager {
}
/**
+ * Creates the singleton AccessibilityManager to be shared across users. This
+ * has to be called before the local AccessibilityManager is created to ensure
+ * it registers itself in the system correctly.
+ * <p>
+ * Note: Calling this method requires INTERACT_ACROSS_USERS_FULL or
+ * INTERACT_ACROSS_USERS permission.
+ * </p>
+ * @param context Context in which this manager operates.
+ * @throws IllegalStateException if not called before the local
+ * AccessibilityManager is instantiated.
+ *
+ * @hide
+ */
+ public static void createAsSharedAcrossUsers(Context context) {
+ synchronized (sInstanceSync) {
+ if (sInstance != null) {
+ throw new IllegalStateException("AccessibilityManager already created.");
+ }
+ createSingletonInstance(context, UserHandle.USER_CURRENT);
+ }
+ }
+
+ /**
* Get an AccessibilityManager instance (create one if necessary).
*
+ * @param context Context in which this manager operates.
+ *
* @hide
*/
public static AccessibilityManager getInstance(Context context) {
synchronized (sInstanceSync) {
if (sInstance == null) {
- IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
- IAccessibilityManager service = IAccessibilityManager.Stub.asInterface(iBinder);
- sInstance = new AccessibilityManager(context, service);
+ createSingletonInstance(context, UserHandle.myUserId());
}
}
return sInstance;
}
/**
+ * Creates the singleton instance.
+ *
+ * @param context Context in which this manager operates.
+ * @param userId The user id under which to operate.
+ */
+ private static void createSingletonInstance(Context context, int userId) {
+ IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
+ IAccessibilityManager service = IAccessibilityManager.Stub.asInterface(iBinder);
+ sInstance = new AccessibilityManager(context, service, userId);
+ }
+
+ /**
* Create an instance.
*
* @param context A {@link Context}.
* @param service An interface to the backing service.
+ * @param userId User id under which to run.
*
* @hide
*/
- public AccessibilityManager(Context context, IAccessibilityManager service) {
+ public AccessibilityManager(Context context, IAccessibilityManager service, int userId) {
mHandler = new MyHandler(context.getMainLooper());
mService = service;
+ mUserId = userId;
try {
- final int stateFlags = mService.addClient(mClient);
+ final int stateFlags = mService.addClient(mClient, userId);
setState(stateFlags);
} catch (RemoteException re) {
Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
@@ -222,7 +262,7 @@ public final class AccessibilityManager {
// client using it is called through Binder from another process. Example: MMS
// app adds a SMS notification and the NotificationManagerService calls this method
long identityToken = Binder.clearCallingIdentity();
- doRecycle = mService.sendAccessibilityEvent(event);
+ doRecycle = mService.sendAccessibilityEvent(event, mUserId);
Binder.restoreCallingIdentity(identityToken);
if (DEBUG) {
Log.i(LOG_TAG, event + " sent");
@@ -244,7 +284,7 @@ public final class AccessibilityManager {
throw new IllegalStateException("Accessibility off. Did you forget to check that?");
}
try {
- mService.interrupt();
+ mService.interrupt(mUserId);
if (DEBUG) {
Log.i(LOG_TAG, "Requested interrupt from all services");
}
@@ -280,7 +320,7 @@ public final class AccessibilityManager {
public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
List<AccessibilityServiceInfo> services = null;
try {
- services = mService.getInstalledAccessibilityServiceList();
+ services = mService.getInstalledAccessibilityServiceList(mUserId);
if (DEBUG) {
Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
}
@@ -307,7 +347,7 @@ public final class AccessibilityManager {
int feedbackTypeFlags) {
List<AccessibilityServiceInfo> services = null;
try {
- services = mService.getEnabledAccessibilityServiceList(feedbackTypeFlags);
+ services = mService.getEnabledAccessibilityServiceList(feedbackTypeFlags, mUserId);
if (DEBUG) {
Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
}
@@ -385,7 +425,7 @@ public final class AccessibilityManager {
public int addAccessibilityInteractionConnection(IWindow windowToken,
IAccessibilityInteractionConnection connection) {
try {
- return mService.addAccessibilityInteractionConnection(windowToken, connection);
+ return mService.addAccessibilityInteractionConnection(windowToken, connection, mUserId);
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error while adding an accessibility interaction connection. ", re);
}
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 5b5134a..60238627 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -34,18 +34,18 @@ import android.view.IWindow;
*/
interface IAccessibilityManager {
- int addClient(IAccessibilityManagerClient client);
+ int addClient(IAccessibilityManagerClient client, int userId);
- boolean sendAccessibilityEvent(in AccessibilityEvent uiEvent);
+ boolean sendAccessibilityEvent(in AccessibilityEvent uiEvent, int userId);
- List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
+ List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId);
- List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType);
+ List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, int userId);
- void interrupt();
+ void interrupt(int userId);
int addAccessibilityInteractionConnection(IWindow windowToken,
- in IAccessibilityInteractionConnection connection);
+ in IAccessibilityInteractionConnection connection, int userId);
void removeAccessibilityInteractionConnection(IWindow windowToken);
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index d23f52c..1c47615 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -4594,11 +4594,11 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
private void ensureSelectionHandles() {
if (mSelectHandleCenter == null) {
mSelectHandleCenter = mContext.getResources().getDrawable(
- com.android.internal.R.drawable.text_select_handle_middle);
+ com.android.internal.R.drawable.text_select_handle_middle).mutate();
mSelectHandleLeft = mContext.getResources().getDrawable(
- com.android.internal.R.drawable.text_select_handle_left);
+ com.android.internal.R.drawable.text_select_handle_left).mutate();
mSelectHandleRight = mContext.getResources().getDrawable(
- com.android.internal.R.drawable.text_select_handle_right);
+ com.android.internal.R.drawable.text_select_handle_right).mutate();
// All handles have the same height, so we can save effort with
// this assumption.
mSelectOffset = new Point(0,
diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java
index fe6c4f5..736566e 100644
--- a/core/java/android/widget/ActivityChooserModel.java
+++ b/core/java/android/widget/ActivityChooserModel.java
@@ -21,7 +21,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.database.DataSetObservable;
-import android.database.DataSetObserver;
import android.os.AsyncTask;
import android.text.TextUtils;
import android.util.Log;
@@ -458,13 +457,18 @@ public class ActivityChooserModel extends DataSetObservable {
* </p>
*
* @return An {@link Intent} for launching the activity or null if the
- * policy has consumed the intent.
+ * policy has consumed the intent or there is not current intent
+ * set via {@link #setIntent(Intent)}.
*
* @see HistoricalRecord
* @see OnChooseActivityListener
*/
public Intent chooseActivity(int index) {
synchronized (mInstanceLock) {
+ if (mIntent == null) {
+ return null;
+ }
+
ensureConsistentState();
ActivityResolveInfo chosenActivity = mActivities.get(index);
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 27d15f6..06dadb0 100755
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -257,7 +257,7 @@ public class AppSecurityPermissions {
try {
pkgInfo = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
} catch (NameNotFoundException e) {
- Log.w(TAG, "Could'nt retrieve permissions for package:"+packageName);
+ Log.w(TAG, "Couldn't retrieve permissions for package:"+packageName);
return;
}
// Extract all user permissions
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index b06da06..361eca4 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -1573,7 +1573,8 @@ public class CalendarView extends FrameLayout {
// If we're showing the week number calculate it based on Monday
int i = 0;
if (mShowWeekNumber) {
- mDayNumbers[0] = Integer.toString(mTempDate.get(Calendar.WEEK_OF_YEAR));
+ mDayNumbers[0] = String.format(Locale.getDefault(), "%d",
+ mTempDate.get(Calendar.WEEK_OF_YEAR));
i++;
}
@@ -1594,7 +1595,8 @@ public class CalendarView extends FrameLayout {
if (mTempDate.before(mMinDate) || mTempDate.after(mMaxDate)) {
mDayNumbers[i] = "";
} else {
- mDayNumbers[i] = Integer.toString(mTempDate.get(Calendar.DAY_OF_MONTH));
+ mDayNumbers[i] = String.format(Locale.getDefault(), "%d",
+ mTempDate.get(Calendar.DAY_OF_MONTH));
}
mTempDate.add(Calendar.DAY_OF_MONTH, 1);
}
@@ -1609,7 +1611,7 @@ public class CalendarView extends FrameLayout {
}
/**
- * Initialize the paint isntances.
+ * Initialize the paint instances.
*/
private void initilaizePaints() {
mDrawPaint.setFakeBoldText(false);
@@ -1620,6 +1622,7 @@ public class CalendarView extends FrameLayout {
mMonthNumDrawPaint.setAntiAlias(true);
mMonthNumDrawPaint.setStyle(Style.FILL);
mMonthNumDrawPaint.setTextAlign(Align.CENTER);
+ mMonthNumDrawPaint.setTextSize(mDateTextSize);
}
/**
@@ -1657,16 +1660,34 @@ public class CalendarView extends FrameLayout {
* @return True if a day was found for the given location.
*/
public boolean getDayFromLocation(float x, Calendar outCalendar) {
- int dayStart = mShowWeekNumber ? mWidth / mNumCells : 0;
- if (x < dayStart || x > mWidth) {
+ final boolean isLayoutRtl = isLayoutRtl();
+
+ int start;
+ int end;
+
+ if (isLayoutRtl) {
+ start = 0;
+ end = mShowWeekNumber ? mWidth - mWidth / mNumCells : mWidth;
+ } else {
+ start = mShowWeekNumber ? mWidth / mNumCells : 0;
+ end = mWidth;
+ }
+
+ if (x < start || x > end) {
outCalendar.clear();
return false;
}
- // Selection is (x - start) / (pixels/day) == (x -s) * day / pixels
- int dayPosition = (int) ((x - dayStart) * mDaysPerWeek
- / (mWidth - dayStart));
+
+ // Selection is (x - start) / (pixels/day) which is (x - start) * day / pixels
+ int dayPosition = (int) ((x - start) * mDaysPerWeek / (end - start));
+
+ if (isLayoutRtl) {
+ dayPosition = mDaysPerWeek - 1 - dayPosition;
+ }
+
outCalendar.setTimeInMillis(mFirstDay.getTimeInMillis());
outCalendar.add(Calendar.DAY_OF_MONTH, dayPosition);
+
return true;
}
@@ -1691,12 +1712,25 @@ public class CalendarView extends FrameLayout {
mTempRect.top = mWeekSeperatorLineWidth;
mTempRect.bottom = mHeight;
- mTempRect.left = mShowWeekNumber ? mWidth / mNumCells : 0;
- mTempRect.right = mSelectedLeft - 2;
+
+ final boolean isLayoutRtl = isLayoutRtl();
+
+ if (isLayoutRtl) {
+ mTempRect.left = 0;
+ mTempRect.right = mSelectedLeft - 2;
+ } else {
+ mTempRect.left = mShowWeekNumber ? mWidth / mNumCells : 0;
+ mTempRect.right = mSelectedLeft - 2;
+ }
canvas.drawRect(mTempRect, mDrawPaint);
- mTempRect.left = mSelectedRight + 3;
- mTempRect.right = mWidth;
+ if (isLayoutRtl) {
+ mTempRect.left = mSelectedRight + 3;
+ mTempRect.right = mShowWeekNumber ? mWidth - mWidth / mNumCells : mWidth;
+ } else {
+ mTempRect.left = mSelectedRight + 3;
+ mTempRect.right = mWidth;
+ }
canvas.drawRect(mTempRect, mDrawPaint);
}
@@ -1706,25 +1740,41 @@ public class CalendarView extends FrameLayout {
* @param canvas The canvas to draw on
*/
private void drawWeekNumbersAndDates(Canvas canvas) {
- float textHeight = mDrawPaint.getTextSize();
- int y = (int) ((mHeight + textHeight) / 2) - mWeekSeperatorLineWidth;
- int nDays = mNumCells;
+ final float textHeight = mDrawPaint.getTextSize();
+ final int y = (int) ((mHeight + textHeight) / 2) - mWeekSeperatorLineWidth;
+ final int nDays = mNumCells;
+ final int divisor = 2 * nDays;
mDrawPaint.setTextAlign(Align.CENTER);
mDrawPaint.setTextSize(mDateTextSize);
+
int i = 0;
- int divisor = 2 * nDays;
- if (mShowWeekNumber) {
- mDrawPaint.setColor(mWeekNumberColor);
- int x = mWidth / divisor;
- canvas.drawText(mDayNumbers[0], x, y, mDrawPaint);
- i++;
- }
- for (; i < nDays; i++) {
- mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor
- : mUnfocusedMonthDateColor);
- int x = (2 * i + 1) * mWidth / divisor;
- canvas.drawText(mDayNumbers[i], x, y, mMonthNumDrawPaint);
+
+ if (isLayoutRtl()) {
+ for (; i < nDays - 1; i++) {
+ mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor
+ : mUnfocusedMonthDateColor);
+ int x = (2 * i + 1) * mWidth / divisor;
+ canvas.drawText(mDayNumbers[nDays - 1 - i], x, y, mMonthNumDrawPaint);
+ }
+ if (mShowWeekNumber) {
+ mDrawPaint.setColor(mWeekNumberColor);
+ int x = mWidth - mWidth / divisor;
+ canvas.drawText(mDayNumbers[0], x, y, mDrawPaint);
+ }
+ } else {
+ if (mShowWeekNumber) {
+ mDrawPaint.setColor(mWeekNumberColor);
+ int x = mWidth / divisor;
+ canvas.drawText(mDayNumbers[0], x, y, mDrawPaint);
+ i++;
+ }
+ for (; i < nDays; i++) {
+ mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor
+ : mUnfocusedMonthDateColor);
+ int x = (2 * i + 1) * mWidth / divisor;
+ canvas.drawText(mDayNumbers[i], x, y, mMonthNumDrawPaint);
+ }
}
}
@@ -1744,8 +1794,16 @@ public class CalendarView extends FrameLayout {
}
mDrawPaint.setColor(mWeekSeparatorLineColor);
mDrawPaint.setStrokeWidth(mWeekSeperatorLineWidth);
- float x = mShowWeekNumber ? mWidth / mNumCells : 0;
- canvas.drawLine(x, 0, mWidth, 0, mDrawPaint);
+ float startX;
+ float stopX;
+ if (isLayoutRtl()) {
+ startX = 0;
+ stopX = mShowWeekNumber ? mWidth - mWidth / mNumCells : mWidth;
+ } else {
+ startX = mShowWeekNumber ? mWidth / mNumCells : 0;
+ stopX = mWidth;
+ }
+ canvas.drawLine(startX, 0, stopX, 0, mDrawPaint);
}
/**
@@ -1778,15 +1836,21 @@ public class CalendarView extends FrameLayout {
*/
private void updateSelectionPositions() {
if (mHasSelectedDay) {
+ final boolean isLayoutRtl = isLayoutRtl();
int selectedPosition = mSelectedDay - mFirstDayOfWeek;
if (selectedPosition < 0) {
selectedPosition += 7;
}
- if (mShowWeekNumber) {
+ if (mShowWeekNumber && !isLayoutRtl) {
selectedPosition++;
}
- mSelectedLeft = selectedPosition * mWidth / mNumCells;
- mSelectedRight = (selectedPosition + 1) * mWidth / mNumCells;
+ if (isLayoutRtl) {
+ mSelectedLeft = (mDaysPerWeek - 1 - selectedPosition) * mWidth / mNumCells;
+
+ } else {
+ mSelectedLeft = selectedPosition * mWidth / mNumCells;
+ }
+ mSelectedRight = mSelectedLeft + mWidth / mNumCells;
}
}
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index ac3bedb..07d3a7a 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -220,7 +220,7 @@ public class DatePicker extends FrameLayout {
// day
mDaySpinner = (NumberPicker) findViewById(R.id.day);
- mDaySpinner.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
+ mDaySpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
mDaySpinner.setOnLongPressUpdateInterval(100);
mDaySpinner.setOnValueChangedListener(onChangeListener);
mDaySpinnerInput = (EditText) mDaySpinner.findViewById(R.id.numberpicker_input);
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index dbc777e..704f6b6 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -51,10 +51,12 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import com.android.internal.R;
+import libcore.icu.LocaleData;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
/**
* A widget that enables the user to select a number form a predefined range.
@@ -138,13 +140,6 @@ public class NumberPicker extends LinearLayout {
private static final int DEFAULT_LAYOUT_RESOURCE_ID = R.layout.number_picker;
/**
- * The numbers accepted by the input text's {@link Filter}
- */
- private static final char[] DIGIT_CHARACTERS = new char[] {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
- };
-
- /**
* Constant for unspecified size.
*/
private static final int SIZE_UNSPECIFIED = -1;
@@ -154,23 +149,53 @@ public class NumberPicker extends LinearLayout {
* strings like "01". Keeping a static formatter etc. is the most efficient
* way to do this; it avoids creating temporary objects on every call to
* format().
- *
- * @hide
*/
- public static final NumberPicker.Formatter TWO_DIGIT_FORMATTER = new NumberPicker.Formatter() {
+ private static class TwoDigitFormatter implements NumberPicker.Formatter {
final StringBuilder mBuilder = new StringBuilder();
- final java.util.Formatter mFmt = new java.util.Formatter(mBuilder, java.util.Locale.US);
+ char mZeroDigit;
+ java.util.Formatter mFmt;
final Object[] mArgs = new Object[1];
+ TwoDigitFormatter() {
+ final Locale locale = Locale.getDefault();
+ init(locale);
+ }
+
+ private void init(Locale locale) {
+ mFmt = createFormatter(locale);
+ mZeroDigit = getZeroDigit(locale);
+ }
+
public String format(int value) {
+ final Locale currentLocale = Locale.getDefault();
+ if (mZeroDigit != getZeroDigit(currentLocale)) {
+ init(currentLocale);
+ }
mArgs[0] = value;
mBuilder.delete(0, mBuilder.length());
mFmt.format("%02d", mArgs);
return mFmt.toString();
}
- };
+
+ private static char getZeroDigit(Locale locale) {
+ return LocaleData.get(locale).zeroDigit;
+ }
+
+ private java.util.Formatter createFormatter(Locale locale) {
+ return new java.util.Formatter(mBuilder, locale);
+ }
+ }
+
+ private static final TwoDigitFormatter sTwoDigitFormatter = new TwoDigitFormatter();
+
+ /**
+ * @hide
+ */
+ public static final Formatter getTwoDigitFormatter() {
+ return sTwoDigitFormatter;
+ }
/**
* The increment button.
@@ -1156,7 +1181,7 @@ public class NumberPicker extends LinearLayout {
if (mDisplayedValues == null) {
float maxDigitWidth = 0;
for (int i = 0; i <= 9; i++) {
- final float digitWidth = mSelectorWheelPaint.measureText(String.valueOf(i));
+ final float digitWidth = mSelectorWheelPaint.measureText(formatNumberWithLocale(i));
if (digitWidth > maxDigitWidth) {
maxDigitWidth = digitWidth;
}
@@ -1689,7 +1714,7 @@ public class NumberPicker extends LinearLayout {
}
private String formatNumber(int value) {
- return (mFormatter != null) ? mFormatter.format(value) : String.valueOf(value);
+ return (mFormatter != null) ? mFormatter.format(value) : formatNumberWithLocale(value);
}
private void validateInputTextView(View v) {
@@ -1849,6 +1874,20 @@ public class NumberPicker extends LinearLayout {
}
/**
+ * The numbers accepted by the input text's {@link Filter}
+ */
+ private static final char[] DIGIT_CHARACTERS = new char[] {
+ // Latin digits are the common case
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ // Arabic-Indic
+ '\u0660', '\u0661', '\u0662', '\u0663', '\u0664', '\u0665', '\u0666', '\u0667', '\u0668'
+ , '\u0669',
+ // Extended Arabic-Indic
+ '\u06f0', '\u06f1', '\u06f2', '\u06f3', '\u06f4', '\u06f5', '\u06f6', '\u06f7', '\u06f8'
+ , '\u06f9'
+ };
+
+ /**
* Filter for accepting only valid indices or prefixes of the string
* representation of valid indices.
*/
@@ -2493,4 +2532,8 @@ public class NumberPicker extends LinearLayout {
return null;
}
}
+
+ static private String formatNumberWithLocale(int value) {
+ return String.format(Locale.getDefault(), "%d", value);
+ }
}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 87ef23f..1a47ce2 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -222,6 +222,14 @@ public class RemoteViews implements Parcelable, Filter {
int viewId;
}
+ /**
+ * Merges the passed RemoteViews actions with this RemoteViews actions according to
+ * action-specific merge rules.
+ *
+ * @param newRv
+ *
+ * @hide
+ */
public void mergeRemoteViews(RemoteViews newRv) {
// We first copy the new RemoteViews, as the process of merging modifies the way the actions
// reference the bitmap cache. We don't want to modify the object as it may need to
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index cb9ed61..e6796cb 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -172,7 +172,7 @@ public class TimePicker extends FrameLayout {
mMinuteSpinner.setMinValue(0);
mMinuteSpinner.setMaxValue(59);
mMinuteSpinner.setOnLongPressUpdateInterval(100);
- mMinuteSpinner.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
+ mMinuteSpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
mMinuteSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
updateInputState();
@@ -500,7 +500,7 @@ public class TimePicker extends FrameLayout {
if (is24HourView()) {
mHourSpinner.setMinValue(0);
mHourSpinner.setMaxValue(23);
- mHourSpinner.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
+ mHourSpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
} else {
mHourSpinner.setMinValue(1);
mHourSpinner.setMaxValue(12);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index f3bef08..09457cc 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -215,36 +215,26 @@ public class LockPatternUtils {
}
public void setCurrentUser(int userId) {
- if (Process.myUid() == Process.SYSTEM_UID) {
- mCurrentUserId = userId;
- } else {
- throw new SecurityException("Only the system process can set the current user");
- }
+ mCurrentUserId = userId;
}
public int getCurrentUser() {
- if (Process.myUid() == Process.SYSTEM_UID) {
- if (mCurrentUserId != UserHandle.USER_NULL) {
- // Someone is regularly updating using setCurrentUser() use that value.
- return mCurrentUserId;
- }
- try {
- return ActivityManagerNative.getDefault().getCurrentUser().id;
- } catch (RemoteException re) {
- return UserHandle.USER_OWNER;
- }
- } else {
- throw new SecurityException("Only the system process can get the current user");
+ if (mCurrentUserId != UserHandle.USER_NULL) {
+ // Someone is regularly updating using setCurrentUser() use that value.
+ return mCurrentUserId;
+ }
+ try {
+ return ActivityManagerNative.getDefault().getCurrentUser().id;
+ } catch (RemoteException re) {
+ return UserHandle.USER_OWNER;
}
}
public void removeUser(int userId) {
- if (Process.myUid() == Process.SYSTEM_UID) {
- try {
- getLockSettings().removeUser(userId);
- } catch (RemoteException re) {
- Log.e(TAG, "Couldn't remove lock settings for user " + userId);
- }
+ try {
+ getLockSettings().removeUser(userId);
+ } catch (RemoteException re) {
+ Log.e(TAG, "Couldn't remove lock settings for user " + userId);
}
}
@@ -591,10 +581,6 @@ public class LockPatternUtils {
// Compute the hash
final byte[] hash = passwordToHash(password);
try {
- if (Process.myUid() != Process.SYSTEM_UID && userHandle != UserHandle.myUserId()) {
- throw new SecurityException(
- "Only the system process can save lock password for another user");
- }
getLockSettings().setLockPassword(hash, userHandle);
DevicePolicyManager dpm = getDevicePolicyManager();
KeyStore keyStore = KeyStore.getInstance();
@@ -1007,8 +993,8 @@ public class LockPatternUtils {
* or null if there is no next alarm.
*/
public String getNextAlarm() {
- String nextAlarm = Settings.System.getString(mContentResolver,
- Settings.System.NEXT_ALARM_FORMATTED);
+ String nextAlarm = Settings.System.getStringForUser(mContentResolver,
+ Settings.System.NEXT_ALARM_FORMATTED, UserHandle.USER_CURRENT);
if (nextAlarm == null || TextUtils.isEmpty(nextAlarm)) {
return null;
}
@@ -1035,8 +1021,9 @@ public class LockPatternUtils {
public int[] getUserDefinedWidgets() {
int appWidgetId = -1;
- String appWidgetIdString = Settings.Secure.getString(
- mContentResolver, Settings.Secure.LOCK_SCREEN_USER_SELECTED_APPWIDGET_ID);
+ String appWidgetIdString = Settings.Secure.getStringForUser(
+ mContentResolver, Settings.Secure.LOCK_SCREEN_USER_SELECTED_APPWIDGET_ID,
+ UserHandle.USER_CURRENT);
if (appWidgetIdString != null) {
appWidgetId = (int) Integer.decode(appWidgetIdString);
}
@@ -1046,8 +1033,9 @@ public class LockPatternUtils {
public int getStatusWidget() {
int appWidgetId = -1;
- String appWidgetIdString = Settings.Secure.getString(
- mContentResolver, Settings.Secure.LOCK_SCREEN_STATUS_APPWIDGET_ID);
+ String appWidgetIdString = Settings.Secure.getStringForUser(
+ mContentResolver, Settings.Secure.LOCK_SCREEN_STATUS_APPWIDGET_ID,
+ UserHandle.USER_CURRENT);
if (appWidgetIdString != null) {
appWidgetId = (int) Integer.decode(appWidgetIdString);
}