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/appwidget/AppWidgetHostView.java7
-rw-r--r--core/java/android/content/pm/PackageManager.java64
-rw-r--r--core/java/android/content/pm/ResolveInfo.java15
-rw-r--r--core/java/android/net/SSLCertificateSocketFactory.java17
-rw-r--r--core/java/android/provider/MediaStore.java1
-rw-r--r--core/java/android/view/HardwareRenderer.java18
-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/widget/ActivityChooserModel.java8
-rwxr-xr-xcore/java/android/widget/AppSecurityPermissions.java2
-rw-r--r--core/java/android/widget/CalendarView.java125
-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
17 files changed, 380 insertions, 111 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/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/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index e3749b4..07117fe 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -230,6 +230,21 @@ public class ResolveInfo implements Parcelable {
public ResolveInfo() {
}
+ public ResolveInfo(ResolveInfo orig) {
+ activityInfo = orig.activityInfo;
+ serviceInfo = orig.serviceInfo;
+ filter = orig.filter;
+ priority = orig.priority;
+ preferredOrder = orig.preferredOrder;
+ match = orig.match;
+ specificIndex = orig.specificIndex;
+ labelRes = orig.labelRes;
+ nonLocalizedLabel = orig.nonLocalizedLabel;
+ icon = orig.icon;
+ resolvePackageName = orig.resolvePackageName;
+ system = orig.system;
+ }
+
public String toString() {
ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo;
return "ResolveInfo{"
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 27cabef..846443d 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -21,6 +21,7 @@ import android.util.Log;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
+import java.net.SocketException;
import java.security.KeyManagementException;
import java.security.cert.X509Certificate;
import javax.net.SocketFactory;
@@ -341,6 +342,22 @@ public class SSLCertificateSocketFactory extends SSLSocketFactory {
castToOpenSSLSocket(socket).setHostname(hostName);
}
+ /**
+ * Sets this socket's SO_SNDTIMEO write timeout in milliseconds.
+ * Use 0 for no timeout.
+ * To take effect, this option must be set before the blocking method was called.
+ *
+ * @param socket a socket created by this factory.
+ * @param timeout the desired write timeout in milliseconds.
+ * @throws IllegalArgumentException if the socket was not created by this factory.
+ *
+ * @hide
+ */
+ public void setSoWriteTimeout(Socket socket, int writeTimeoutMilliseconds)
+ throws SocketException {
+ castToOpenSSLSocket(socket).setSoWriteTimeout(writeTimeoutMilliseconds);
+ }
+
private static OpenSSLSocketImpl castToOpenSSLSocket(Socket socket) {
if (!(socket instanceof OpenSSLSocketImpl)) {
throw new IllegalArgumentException("Socket not created by this factory: "
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 3c90f1c..0e7ab52 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -255,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/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index e0e8de3..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.
*
@@ -649,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;
@@ -698,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
@@ -1414,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
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/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 6ddfc3b..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);
}
@@ -1658,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;
}
@@ -1692,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);
}
@@ -1707,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);
+ }
}
}
@@ -1745,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);
}
/**
@@ -1779,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 5d65324..90f55bf 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -228,6 +228,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);
}