summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/accounts/AccountManager.java4
-rw-r--r--core/java/android/app/ActionBar.java15
-rw-r--r--core/java/android/app/ActivityManagerNative.java29
-rw-r--r--core/java/android/app/ActivityThread.java14
-rw-r--r--core/java/android/app/ContextImpl.java4
-rw-r--r--core/java/android/app/Fragment.java8
-rw-r--r--core/java/android/app/IActivityManager.java3
-rw-r--r--core/java/android/app/MediaRouteButton.java3
-rw-r--r--core/java/android/app/Notification.java18
-rw-r--r--core/java/android/app/PendingIntent.java14
-rw-r--r--core/java/android/app/Presentation.java2
-rw-r--r--core/java/android/app/SearchManager.java3
-rw-r--r--core/java/android/app/Service.java4
-rw-r--r--core/java/android/appwidget/AppWidgetHost.java62
-rw-r--r--core/java/android/appwidget/AppWidgetHostView.java17
-rw-r--r--core/java/android/appwidget/AppWidgetManager.java26
-rwxr-xr-xcore/java/android/bluetooth/BluetoothAdapter.java4
-rw-r--r--core/java/android/bluetooth/BluetoothSocket.java18
-rw-r--r--core/java/android/content/Intent.java6
-rw-r--r--core/java/android/content/SyncManager.java3
-rw-r--r--core/java/android/content/SyncStorageEngine.java64
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl1
-rw-r--r--core/java/android/content/pm/PackageManager.java86
-rw-r--r--core/java/android/content/pm/RegisteredServicesCache.java62
-rw-r--r--core/java/android/hardware/SensorEvent.java4
-rw-r--r--core/java/android/hardware/SensorManager.java10
-rw-r--r--core/java/android/hardware/display/WifiDisplay.java9
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java15
-rw-r--r--core/java/android/net/DhcpStateMachine.java2
-rw-r--r--core/java/android/net/NetworkStats.java9
-rw-r--r--core/java/android/net/NetworkTemplate.java3
-rw-r--r--core/java/android/os/BatteryStats.java96
-rw-r--r--core/java/android/os/Environment.java4
-rw-r--r--core/java/android/os/ParcelFileDescriptor.java61
-rw-r--r--core/java/android/os/PowerManager.java2
-rw-r--r--core/java/android/os/Trace.java10
-rw-r--r--core/java/android/provider/CalendarContract.java17
-rwxr-xr-xcore/java/android/provider/ContactsContract.java6
-rw-r--r--core/java/android/provider/Settings.java28
-rw-r--r--core/java/android/server/search/SearchManagerService.java2
-rw-r--r--core/java/android/text/format/DateUtils.java24
-rw-r--r--core/java/android/util/AttributeSet.java4
-rw-r--r--core/java/android/util/DisplayMetrics.java17
-rw-r--r--core/java/android/util/IntProperty.java2
-rw-r--r--core/java/android/view/DisplayInfo.java10
-rw-r--r--core/java/android/view/HardwareRenderer.java20
-rw-r--r--core/java/android/view/IWindowManager.aidl2
-rw-r--r--core/java/android/view/ScaleGestureDetector.java4
-rw-r--r--core/java/android/view/Surface.java19
-rw-r--r--core/java/android/view/View.java2
-rw-r--r--core/java/android/view/ViewGroup.java17
-rw-r--r--core/java/android/view/VolumePanel.java1
-rw-r--r--core/java/android/view/WindowManager.java7
-rw-r--r--core/java/android/widget/CompoundButton.java9
-rw-r--r--core/java/android/widget/Editor.java136
-rw-r--r--core/java/android/widget/RelativeLayout.java48
-rw-r--r--core/java/android/widget/RemoteViewsAdapter.java105
-rw-r--r--core/java/android/widget/ShareActionProvider.java64
-rw-r--r--core/java/android/widget/TextView.java272
-rw-r--r--core/java/android/widget/Toast.java7
-rw-r--r--core/java/android/widget/VideoView.java13
-rw-r--r--core/java/com/android/internal/annotations/GuardedBy.java32
-rw-r--r--core/java/com/android/internal/annotations/Immutable.java30
-rw-r--r--core/java/com/android/internal/annotations/VisibleForTesting.java50
-rw-r--r--core/java/com/android/internal/app/ActionBarImpl.java5
-rw-r--r--core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java25
-rw-r--r--core/java/com/android/internal/appwidget/IAppWidgetService.aidl10
-rw-r--r--core/java/com/android/internal/content/PackageHelper.java2
-rw-r--r--core/java/com/android/internal/net/NetworkStatsFactory.java3
-rw-r--r--core/java/com/android/internal/util/LocalLog.java66
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java193
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java13
72 files changed, 1439 insertions, 521 deletions
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index bcb35d5..03a7e34 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -781,7 +781,7 @@ public class AccountManager {
* {@link android.Manifest.permission#USE_CREDENTIALS}.
*
* @param account The account to fetch an auth token for
- * @param authTokenType The auth token type, see {#link getAuthToken}
+ * @param authTokenType The auth token type, see {@link #getAuthToken getAuthToken()}
* @param notifyAuthFailure If true, display a notification and return null
* if authentication fails; if false, prompt and wait for the user to
* re-enter correct credentials before returning
@@ -1853,7 +1853,7 @@ public class AccountManager {
* <p>
* The most common case is to call this with one account type, e.g.:
* <p>
- * <pre> newChooseAccountsIntent(null, null, new String[]{"com.google"}, false, null,
+ * <pre> newChooseAccountIntent(null, null, new String[]{"com.google"}, false, null,
* null, null, null);</pre>
* @param selectedAccount if specified, indicates that the {@link Account} is the currently
* selected one, according to the caller's definition of selected.
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 2337790..3602fc4 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -132,6 +132,12 @@ public abstract class ActionBar {
public static final int DISPLAY_SHOW_CUSTOM = 0x10;
/**
+ * Allow the title to wrap onto multiple lines if space is available
+ * @hide pending API approval
+ */
+ public static final int DISPLAY_TITLE_MULTIPLE_LINES = 0x20;
+
+ /**
* Set the action bar into custom navigation mode, supplying a view
* for custom navigation.
*
@@ -680,6 +686,15 @@ public abstract class ActionBar {
public Context getThemedContext() { return null; }
/**
+ * Returns true if the Title field has been truncated during layout for lack
+ * of available space.
+ *
+ * @return true if the Title field has been truncated
+ * @hide pending API approval
+ */
+ public boolean isTitleTruncated() { return false; }
+
+ /**
* Listener interface for ActionBar navigation events.
*/
public interface OnNavigationListener {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 67d3930..61b2067 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1701,6 +1701,21 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case GET_INTENT_FOR_INTENT_SENDER_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IIntentSender r = IIntentSender.Stub.asInterface(
+ data.readStrongBinder());
+ Intent intent = getIntentForIntentSender(r);
+ reply.writeNoException();
+ if (intent != null) {
+ reply.writeInt(1);
+ intent.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ } else {
+ reply.writeInt(0);
+ }
+ return true;
+ }
+
case UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
Configuration config = Configuration.CREATOR.createFromParcel(data);
@@ -3977,6 +3992,20 @@ class ActivityManagerProxy implements IActivityManager
return res;
}
+ public Intent getIntentForIntentSender(IIntentSender sender) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(sender.asBinder());
+ mRemote.transact(GET_INTENT_FOR_INTENT_SENDER_TRANSACTION, data, reply, 0);
+ reply.readException();
+ Intent res = reply.readInt() != 0
+ ? Intent.CREATOR.createFromParcel(reply) : null;
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
+
public void updatePersistentConfiguration(Configuration values) throws RemoteException
{
Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 456d757..d880817 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4421,12 +4421,14 @@ public final class ActivityThread {
new ArrayList<IActivityManager.ContentProviderHolder>();
for (ProviderInfo cpi : providers) {
- StringBuilder buf = new StringBuilder(128);
- buf.append("Pub ");
- buf.append(cpi.authority);
- buf.append(": ");
- buf.append(cpi.name);
- Log.i(TAG, buf.toString());
+ if (DEBUG_PROVIDER) {
+ StringBuilder buf = new StringBuilder(128);
+ buf.append("Pub ");
+ buf.append(cpi.authority);
+ buf.append(": ");
+ buf.append(cpi.name);
+ Log.i(TAG, buf.toString());
+ }
IActivityManager.ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
if (cph != null) {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 95b6bed..f895ccc 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -168,7 +168,7 @@ class ReceiverRestrictedContext extends ContextWrapper {
* context object for Activity and other application components.
*/
class ContextImpl extends Context {
- private final static String TAG = "ApplicationContext";
+ private final static String TAG = "ContextImpl";
private final static boolean DEBUG = false;
private static final HashMap<String, SharedPreferencesImpl> sSharedPrefs =
@@ -1715,7 +1715,7 @@ class ContextImpl extends Context {
private void warnIfCallingFromSystemProcess() {
if (Process.myUid() == Process.SYSTEM_UID) {
Slog.w(TAG, "Calling a method in the system process without a qualified user: "
- + Debug.getCallers(3));
+ + Debug.getCallers(5));
}
}
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 34fe215..422d0bc 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1023,7 +1023,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
}
/**
- * Call {@link Activity#startActivity(Intent)} on the fragment's
+ * Call {@link Activity#startActivity(Intent)} from the fragment's
* containing Activity.
*
* @param intent The intent to start.
@@ -1033,7 +1033,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
}
/**
- * Call {@link Activity#startActivity(Intent, Bundle)} on the fragment's
+ * Call {@link Activity#startActivity(Intent, Bundle)} from the fragment's
* containing Activity.
*
* @param intent The intent to start.
@@ -1055,7 +1055,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
}
/**
- * Call {@link Activity#startActivityForResult(Intent, int)} on the fragment's
+ * Call {@link Activity#startActivityForResult(Intent, int)} from the fragment's
* containing Activity.
*/
public void startActivityForResult(Intent intent, int requestCode) {
@@ -1063,7 +1063,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
}
/**
- * Call {@link Activity#startActivityForResult(Intent, int, Bundle)} on the fragment's
+ * Call {@link Activity#startActivityForResult(Intent, int, Bundle)} from the fragment's
* containing Activity.
*/
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 8fc1c86..8af17a4 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -341,6 +341,8 @@ public interface IActivityManager extends IInterface {
public boolean isIntentSenderAnActivity(IIntentSender sender) throws RemoteException;
+ public Intent getIntentForIntentSender(IIntentSender sender) throws RemoteException;
+
public void updatePersistentConfiguration(Configuration values) throws RemoteException;
public long[] getProcessPss(int[] pids) throws RemoteException;
@@ -621,4 +623,5 @@ public interface IActivityManager extends IInterface {
int REQUEST_BUG_REPORT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+157;
int INPUT_DISPATCHING_TIMED_OUT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+158;
int CLEAR_PENDING_BACKUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+159;
+ int GET_INTENT_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+160;
}
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java
index 3ecafc3..a1a147a 100644
--- a/core/java/android/app/MediaRouteButton.java
+++ b/core/java/android/app/MediaRouteButton.java
@@ -217,7 +217,8 @@ public class MediaRouteButton extends View {
void updateRemoteIndicator() {
final RouteInfo selected = mRouter.getSelectedRoute(mRouteTypes);
final boolean isRemote = selected != mRouter.getSystemAudioRoute();
- final boolean isConnecting = selected.getStatusCode() == RouteInfo.STATUS_CONNECTING;
+ final boolean isConnecting = selected != null &&
+ selected.getStatusCode() == RouteInfo.STATUS_CONNECTING;
boolean needsRefresh = false;
if (mRemoteActive != isRemote) {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 2c92d09..3f8e16c 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -322,7 +322,7 @@ public class Notification implements Parcelable
/**
* Bit to be bitwise-ored into the {@link #flags} field that should be
* set if the notification should be canceled when it is clicked by the
- * user. On tablets, the
+ * user.
*/
public static final int FLAG_AUTO_CANCEL = 0x00000010;
@@ -388,8 +388,8 @@ public class Notification implements Parcelable
* Priority is an indication of how much of the user's valuable attention should be consumed by
* this notification. Low-priority notifications may be hidden from the user in certain
* situations, while the user might be interrupted for a higher-priority notification. The
- * system will make a determination about how to interpret notification priority as described in
- * MUMBLE MUMBLE.
+ * system will make a determination about how to interpret this priority when presenting
+ * the notification.
*/
public int priority;
@@ -846,7 +846,9 @@ public class Notification implements Parcelable
}
// TODO(dsandler): defaults take precedence over local values, so reorder the branches below
sb.append(" vibrate=");
- if (this.vibrate != null) {
+ if ((this.defaults & DEFAULT_VIBRATE) != 0) {
+ sb.append("default");
+ } else if (this.vibrate != null) {
int N = this.vibrate.length-1;
sb.append("[");
for (int i=0; i<N; i++) {
@@ -857,16 +859,14 @@ public class Notification implements Parcelable
sb.append(this.vibrate[N]);
}
sb.append("]");
- } else if ((this.defaults & DEFAULT_VIBRATE) != 0) {
- sb.append("default");
} else {
sb.append("null");
}
sb.append(" sound=");
- if (this.sound != null) {
- sb.append(this.sound.toString());
- } else if ((this.defaults & DEFAULT_SOUND) != 0) {
+ if ((this.defaults & DEFAULT_SOUND) != 0) {
sb.append("default");
+ } else if (this.sound != null) {
+ sb.append(this.sound.toString());
} else {
sb.append("null");
}
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index d36d99d..5c75aff 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -790,6 +790,20 @@ public final class PendingIntent implements Parcelable {
}
/**
+ * @hide
+ * Return the Intent of this PendingIntent.
+ */
+ public Intent getIntent() {
+ try {
+ return ActivityManagerNative.getDefault()
+ .getIntentForIntentSender(mTarget);
+ } catch (RemoteException e) {
+ // Should never happen.
+ return null;
+ }
+ }
+
+ /**
* Comparison operator on two PendingIntent objects, such that true
* is returned then they both represent the same operation from the
* same package. This allows you to use {@link #getActivity},
diff --git a/core/java/android/app/Presentation.java b/core/java/android/app/Presentation.java
index 16a0c57..bb45abb4 100644
--- a/core/java/android/app/Presentation.java
+++ b/core/java/android/app/Presentation.java
@@ -281,7 +281,7 @@ public class Presentation extends Dialog {
private boolean isConfigurationStillValid() {
DisplayMetrics dm = new DisplayMetrics();
mDisplay.getMetrics(dm);
- return dm.equals(getResources().getDisplayMetrics());
+ return dm.equalsPhysical(getResources().getDisplayMetrics());
}
private static Context createPresentationContext(
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 43a163d..6382cee 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -858,6 +858,9 @@ public class SearchManager
*/
public Intent getAssistIntent(Context context, int userHandle) {
try {
+ if (mService == null) {
+ return null;
+ }
ComponentName comp = mService.getAssistIntent(userHandle);
if (comp == null) {
return null;
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 02cf3aa..4fbca73 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -666,7 +666,9 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac
/**
* Print the Service's state into the given stream. This gets invoked if
- * you run "adb shell dumpsys activity service &lt;yourservicename&gt;".
+ * you run "adb shell dumpsys activity service &lt;yourservicename&gt;"
+ * (note that for this command to work, the service must be running, and
+ * you must specify a fully-qualified service name).
* This is distinct from "dumpsys &lt;servicename&gt;", which only works for
* named system services and which invokes the {@link IBinder#dump} method
* on the {@link IBinder} interface registered with ServiceManager.
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index cb61a71..fa3bf4d 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -60,6 +60,7 @@ public class AppWidgetHost {
public void updateAppWidget(int appWidgetId, RemoteViews views) {
if (isLocalBinder() && views != null) {
views = views.clone();
+ views.setUser(mUser);
}
Message msg = mHandler.obtainMessage(HANDLE_UPDATE);
msg.arg1 = appWidgetId;
@@ -123,6 +124,8 @@ public class AppWidgetHost {
Callbacks mCallbacks = new Callbacks();
final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<Integer, AppWidgetHostView>();
private OnClickHandler mOnClickHandler;
+ // Optionally set by lockscreen
+ private UserHandle mUser;
public AppWidgetHost(Context context, int hostId) {
this(context, hostId, null, context.getMainLooper());
@@ -137,9 +140,15 @@ public class AppWidgetHost {
mOnClickHandler = handler;
mHandler = new UpdateHandler(looper);
mDisplayMetrics = context.getResources().getDisplayMetrics();
+ mUser = Process.myUserHandle();
bindService();
}
+ /** @hide */
+ public void setUserId(int userId) {
+ mUser = new UserHandle(userId);
+ }
+
private static void bindService() {
synchronized (sServiceLock) {
if (sService == null) {
@@ -154,6 +163,15 @@ public class AppWidgetHost {
* becomes visible, i.e. from onStart() in your Activity.
*/
public void startListening() {
+ startListeningAsUser(UserHandle.myUserId());
+ }
+
+ /**
+ * Start receiving onAppWidgetChanged calls for your AppWidgets. Call this when your activity
+ * becomes visible, i.e. from onStart() in your Activity.
+ * @hide
+ */
+ public void startListeningAsUser(int userId) {
int[] updatedIds;
ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
@@ -161,7 +179,8 @@ public class AppWidgetHost {
if (mPackageName == null) {
mPackageName = mContext.getPackageName();
}
- updatedIds = sService.startListening(mCallbacks, mPackageName, mHostId, updatedViews);
+ updatedIds = sService.startListeningAsUser(
+ mCallbacks, mPackageName, mHostId, updatedViews, userId);
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -169,6 +188,9 @@ public class AppWidgetHost {
final int N = updatedIds.length;
for (int i=0; i<N; i++) {
+ if (updatedViews.get(i) != null) {
+ updatedViews.get(i).setUser(new UserHandle(userId));
+ }
updateAppWidgetView(updatedIds[i], updatedViews.get(i));
}
}
@@ -179,11 +201,27 @@ public class AppWidgetHost {
*/
public void stopListening() {
try {
- sService.stopListening(mHostId);
+ sService.stopListeningAsUser(mHostId, UserHandle.myUserId());
+ }
+ catch (RemoteException e) {
+ throw new RuntimeException("system server dead?", e);
+ }
+ }
+
+ /**
+ * Stop receiving onAppWidgetChanged calls for your AppWidgets. Call this when your activity is
+ * no longer visible, i.e. from onStop() in your Activity.
+ * @hide
+ */
+ public void stopListeningAsUser(int userId) {
+ try {
+ sService.stopListeningAsUser(mHostId, userId);
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
}
+ // Also clear the views
+ clearViews();
}
/**
@@ -224,6 +262,22 @@ public class AppWidgetHost {
}
}
+ /**
+ * Gets a list of all the appWidgetIds that are bound to the current host
+ *
+ * @hide
+ */
+ public int[] getAppWidgetIds() {
+ try {
+ if (sService == null) {
+ bindService();
+ }
+ return sService.getAppWidgetIdsForHost(mHostId);
+ } catch (RemoteException e) {
+ throw new RuntimeException("system server dead?", e);
+ }
+ }
+
private static void checkCallerIsSystem() {
int uid = Process.myUid();
if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
@@ -308,6 +362,7 @@ public class AppWidgetHost {
public final AppWidgetHostView createView(Context context, int appWidgetId,
AppWidgetProviderInfo appWidget) {
AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget);
+ view.setUserId(mUser.getIdentifier());
view.setOnClickHandler(mOnClickHandler);
view.setAppWidget(appWidgetId, appWidget);
synchronized (mViews) {
@@ -316,6 +371,9 @@ public class AppWidgetHost {
RemoteViews views;
try {
views = sService.getAppWidgetViews(appWidgetId);
+ if (views != null) {
+ views.setUser(mUser);
+ }
} catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
}
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 52771ee..700bba8 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -31,7 +31,9 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.Process;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
@@ -85,6 +87,7 @@ public class AppWidgetHostView extends FrameLayout {
Bitmap mOld;
Paint mOldPaint = new Paint();
private OnClickHandler mOnClickHandler;
+ private UserHandle mUser;
/**
* Create a host view. Uses default fade animations.
@@ -112,12 +115,17 @@ public class AppWidgetHostView extends FrameLayout {
public AppWidgetHostView(Context context, int animationIn, int animationOut) {
super(context);
mContext = context;
-
+ mUser = Process.myUserHandle();
// We want to segregate the view ids within AppWidgets to prevent
// problems when those ids collide with view ids in the AppWidgetHost.
setIsRootNamespace(true);
}
+ /** @hide */
+ public void setUserId(int userId) {
+ mUser = new UserHandle(userId);
+ }
+
/**
* Pass the given handler to RemoteViews when updating this widget. Unless this
* is done immediatly after construction, a call to {@link #updateAppWidget(RemoteViews)}
@@ -465,7 +473,8 @@ public class AppWidgetHostView extends FrameLayout {
try {
// Return if cloned successfully, otherwise default
- return mContext.createPackageContext(packageName, Context.CONTEXT_RESTRICTED);
+ return mContext.createPackageContextAsUser(packageName, Context.CONTEXT_RESTRICTED,
+ mUser);
} catch (NameNotFoundException e) {
Log.e(TAG, "Package name " + packageName + " not found");
return mContext;
@@ -539,8 +548,8 @@ public class AppWidgetHostView extends FrameLayout {
try {
if (mInfo != null) {
- Context theirContext = mContext.createPackageContext(
- mInfo.provider.getPackageName(), Context.CONTEXT_RESTRICTED);
+ Context theirContext = mContext.createPackageContextAsUser(
+ mInfo.provider.getPackageName(), Context.CONTEXT_RESTRICTED, mUser);
mRemoteContext = theirContext;
LayoutInflater inflater = (LayoutInflater)
theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 285bc0c..6b1c3e2 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -23,6 +23,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.widget.RemoteViews;
@@ -544,8 +545,19 @@ public class AppWidgetManager {
* Return a list of the AppWidget providers that are currently installed.
*/
public List<AppWidgetProviderInfo> getInstalledProviders() {
+ return getInstalledProviders(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
+ }
+
+ /**
+ * Return a list of the AppWidget providers that are currently installed.
+ *
+ * @param categoryFilter Will only return providers which register as any of the specified
+ * specified categories. See {@link AppWidgetProviderInfo#widgetCategory}.
+ * @hide
+ */
+ public List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter) {
try {
- List<AppWidgetProviderInfo> providers = sService.getInstalledProviders();
+ List<AppWidgetProviderInfo> providers = sService.getInstalledProviders(categoryFilter);
for (AppWidgetProviderInfo info : providers) {
// Converting complex to dp.
info.minWidth =
@@ -738,11 +750,14 @@ public class AppWidgetManager {
* @param intent The intent of the service which will be providing the data to the
* RemoteViewsAdapter.
* @param connection The callback interface to be notified when a connection is made or lost.
+ * @param userHandle The user to bind to.
* @hide
*/
- public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection) {
+ public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection,
+ UserHandle userHandle) {
try {
- sService.bindRemoteViewsService(appWidgetId, intent, connection);
+ sService.bindRemoteViewsService(appWidgetId, intent, connection,
+ userHandle.getIdentifier());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
@@ -758,11 +773,12 @@ public class AppWidgetManager {
* @param appWidgetId The AppWidget instance for which to bind the RemoteViewsService.
* @param intent The intent of the service which will be providing the data to the
* RemoteViewsAdapter.
+ * @param userHandle The user to unbind from.
* @hide
*/
- public void unbindRemoteViewsService(int appWidgetId, Intent intent) {
+ public void unbindRemoteViewsService(int appWidgetId, Intent intent, UserHandle userHandle) {
try {
- sService.unbindRemoteViewsService(appWidgetId, intent);
+ sService.unbindRemoteViewsService(appWidgetId, intent, userHandle.getIdentifier());
}
catch (RemoteException e) {
throw new RuntimeException("system server dead?", e);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index f817fb4..6367e16 100755
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1212,7 +1212,7 @@ public final class BluetoothAdapter {
final private IBluetoothManagerCallback mManagerCallback =
new IBluetoothManagerCallback.Stub() {
public void onBluetoothServiceUp(IBluetooth bluetoothService) {
- if (DBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
+ if (VDBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
synchronized (mManagerCallback) {
mService = bluetoothService;
for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
@@ -1228,7 +1228,7 @@ public final class BluetoothAdapter {
}
public void onBluetoothServiceDown() {
- if (DBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
+ if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
synchronized (mManagerCallback) {
mService = null;
for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 26bde19..8029a1a 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -300,7 +300,6 @@ public final class BluetoothSocket implements Closeable {
if (mDevice == null) throw new IOException("Connect is called on null device");
try {
- // TODO(BT) derive flag from auth and encrypt
if (mSocketState == SocketState.CLOSED) throw new IOException("socket closed");
IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(null);
if (bluetoothProxy == null) throw new IOException("Bluetooth is off");
@@ -349,7 +348,6 @@ public final class BluetoothSocket implements Closeable {
mUuid, mPort, getSecurityFlags());
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
- // TODO(BT) right error code?
return -1;
}
@@ -388,8 +386,13 @@ public final class BluetoothSocket implements Closeable {
/*package*/ BluetoothSocket accept(int timeout) throws IOException {
BluetoothSocket acceptedSocket;
if (mSocketState != SocketState.LISTENING) throw new IOException("bt socket is not in listen state");
- // TODO(BT) wait on an incoming connection
+ if(timeout > 0) {
+ Log.d(TAG, "accept() set timeout (ms):" + timeout);
+ mSocket.setSoTimeout(timeout);
+ }
String RemoteAddr = waitSocketSignal(mSocketIS);
+ if(timeout > 0)
+ mSocket.setSoTimeout(0);
synchronized(this)
{
if (mSocketState != SocketState.LISTENING)
@@ -397,8 +400,6 @@ public final class BluetoothSocket implements Closeable {
acceptedSocket = acceptSocket(RemoteAddr);
//quick drop the reference of the file handle
}
- // TODO(BT) rfcomm socket only supports one connection, return this?
- // return this;
return acceptedSocket;
}
@@ -428,7 +429,7 @@ public final class BluetoothSocket implements Closeable {
@Override
public void close() throws IOException {
- Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: " + mSocketState);
+ if (VDBG) Log.d(TAG, "close() in, this: " + this + ", channel: " + mPort + ", state: " + mSocketState);
if(mSocketState == SocketState.CLOSED)
return;
else
@@ -451,7 +452,6 @@ public final class BluetoothSocket implements Closeable {
mPfd.detachFd();
}
}
- // TODO(BT) unbind proxy,
}
/*package */ void removeChannel() {
@@ -471,6 +471,8 @@ public final class BluetoothSocket implements Closeable {
ByteBuffer bb = ByteBuffer.wrap(sig);
bb.order(ByteOrder.nativeOrder());
int size = bb.getShort();
+ if(size != SOCK_SIGNAL_SIZE)
+ throw new IOException("Connection failure, wrong signal size: " + size);
byte [] addr = new byte[6];
bb.get(addr);
int channel = bb.getInt();
@@ -487,7 +489,7 @@ public final class BluetoothSocket implements Closeable {
while(left > 0) {
int ret = is.read(b, b.length - left, left);
if(ret <= 0)
- throw new IOException("read failed, socket might closed, read ret: " + ret);
+ throw new IOException("read failed, socket might closed or timeout, read ret: " + ret);
left -= ret;
if(left != 0)
Log.w(TAG, "readAll() looping, read partial size: " + (b.length - left) +
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index cf0603e..72b0a8b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2231,7 +2231,7 @@ public class Intent implements Parcelable, Cloneable {
/**
* Broadcast Action: An outgoing call is about to be placed.
*
- * <p>The Intent will have the following extra value:
+ * <p>The Intent will have the following extra value:</p>
* <ul>
* <li><em>{@link android.content.Intent#EXTRA_PHONE_NUMBER}</em> -
* the phone number originally intended to be dialed.</li>
@@ -2255,6 +2255,10 @@ public class Intent implements Parcelable, Cloneable {
* <p>Emergency calls cannot be intercepted using this mechanism, and
* other calls cannot be modified to call emergency numbers using this
* mechanism.
+ * <p>Some apps (such as VoIP apps) may want to redirect the outgoing
+ * call to use their own service instead. Those apps should first prevent
+ * the call from being placed by setting resultData to <code>null</code>
+ * and then start their own app to make the call.
* <p>You must hold the
* {@link android.Manifest.permission#PROCESS_OUTGOING_CALLS}
* permission to receive this Intent.</p>
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 977b461..e4b4b97 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -58,6 +58,7 @@ import android.util.Pair;
import android.util.Slog;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -155,7 +156,7 @@ public class SyncManager {
private SyncStorageEngine mSyncStorageEngine;
- // @GuardedBy("mSyncQueue")
+ @GuardedBy("mSyncQueue")
private final SyncQueue mSyncQueue;
protected final ArrayList<ActiveSyncContext> mActiveSyncContexts = Lists.newArrayList();
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index 10e7bff..1ecab09 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -16,6 +16,7 @@
package android.content;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
@@ -63,6 +64,7 @@ import java.util.List;
public class SyncStorageEngine extends Handler {
private static final String TAG = "SyncManager";
+ private static final boolean DEBUG = false;
private static final boolean DEBUG_FILE = false;
private static final String XML_ATTR_NEXT_AUTHORITY_ID = "nextAuthorityId";
@@ -74,7 +76,7 @@ public class SyncStorageEngine extends Handler {
private static final long DEFAULT_POLL_FREQUENCY_SECONDS = 60 * 60 * 24; // One day
- // @VisibleForTesting
+ @VisibleForTesting
static final long MILLIS_IN_4WEEKS = 1000L * 60 * 60 * 24 * 7 * 4;
/** Enum value for a sync start event. */
@@ -442,7 +444,7 @@ public class SyncStorageEngine extends Handler {
mChangeListeners.finishBroadcast();
}
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
Log.v(TAG, "reportChange " + which + " to: " + reports);
}
@@ -483,13 +485,17 @@ public class SyncStorageEngine extends Handler {
public void setSyncAutomatically(Account account, int userId, String providerName,
boolean sync) {
- Log.d(TAG, "setSyncAutomatically: " + /* account + */" provider " + providerName
- + ", user " + userId + " -> " + sync);
+ if (DEBUG) {
+ Log.d(TAG, "setSyncAutomatically: " + /* account + */" provider " + providerName
+ + ", user " + userId + " -> " + sync);
+ }
synchronized (mAuthorities) {
AuthorityInfo authority = getOrCreateAuthorityLocked(account, userId, providerName, -1,
false);
if (authority.enabled == sync) {
- Log.d(TAG, "setSyncAutomatically: already set to " + sync + ", doing nothing");
+ if (DEBUG) {
+ Log.d(TAG, "setSyncAutomatically: already set to " + sync + ", doing nothing");
+ }
return;
}
authority.enabled = sync;
@@ -531,13 +537,17 @@ public class SyncStorageEngine extends Handler {
} else if (syncable < -1) {
syncable = -1;
}
- Log.d(TAG, "setIsSyncable: " + account + ", provider " + providerName
- + ", user " + userId + " -> " + syncable);
+ if (DEBUG) {
+ Log.d(TAG, "setIsSyncable: " + account + ", provider " + providerName
+ + ", user " + userId + " -> " + syncable);
+ }
synchronized (mAuthorities) {
AuthorityInfo authority = getOrCreateAuthorityLocked(account, userId, providerName, -1,
false);
if (authority.syncable == syncable) {
- Log.d(TAG, "setIsSyncable: already set to " + syncable + ", doing nothing");
+ if (DEBUG) {
+ Log.d(TAG, "setIsSyncable: already set to " + syncable + ", doing nothing");
+ }
return;
}
authority.syncable = syncable;
@@ -563,7 +573,7 @@ public class SyncStorageEngine extends Handler {
public void setBackoff(Account account, int userId, String providerName,
long nextSyncTime, long nextDelay) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
Log.v(TAG, "setBackoff: " + account + ", provider " + providerName
+ ", user " + userId
+ " -> nextSyncTime " + nextSyncTime + ", nextDelay " + nextDelay);
@@ -614,7 +624,7 @@ public class SyncStorageEngine extends Handler {
for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
if (authorityInfo.backoffTime != NOT_IN_BACKOFF_MODE
|| authorityInfo.backoffDelay != NOT_IN_BACKOFF_MODE) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
Log.v(TAG, "clearAllBackoffs:"
+ " authority:" + authorityInfo.authority
+ " account:" + accountInfo.accountAndUser.account.name
@@ -640,7 +650,7 @@ public class SyncStorageEngine extends Handler {
public void setDelayUntilTime(Account account, int userId, String providerName,
long delayUntil) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
Log.v(TAG, "setDelayUntil: " + account + ", provider " + providerName
+ ", user " + userId + " -> delayUntil " + delayUntil);
}
@@ -676,7 +686,7 @@ public class SyncStorageEngine extends Handler {
if (extras == null) {
extras = new Bundle();
}
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
Log.v(TAG, "addOrRemovePeriodicSync: " + account + ", user " + userId
+ ", provider " + providerName
+ " -> period " + period + ", extras " + extras);
@@ -832,7 +842,7 @@ public class SyncStorageEngine extends Handler {
public PendingOperation insertIntoPending(PendingOperation op) {
synchronized (mAuthorities) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
Log.v(TAG, "insertIntoPending: account=" + op.account
+ " user=" + op.userId
+ " auth=" + op.authority
@@ -864,7 +874,7 @@ public class SyncStorageEngine extends Handler {
public boolean deleteFromPending(PendingOperation op) {
boolean res = false;
synchronized (mAuthorities) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
Log.v(TAG, "deleteFromPending: account=" + op.account
+ " user=" + op.userId
+ " auth=" + op.authority
@@ -883,7 +893,7 @@ public class SyncStorageEngine extends Handler {
AuthorityInfo authority = getAuthorityLocked(op.account, op.userId, op.authority,
"deleteFromPending");
if (authority != null) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "removing - " + authority);
+ if (DEBUG) Log.v(TAG, "removing - " + authority);
final int N = mPendingOperations.size();
boolean morePending = false;
for (int i=0; i<N; i++) {
@@ -897,7 +907,7 @@ public class SyncStorageEngine extends Handler {
}
if (!morePending) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "no more pending!");
+ if (DEBUG) Log.v(TAG, "no more pending!");
SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
status.pending = false;
}
@@ -937,7 +947,7 @@ public class SyncStorageEngine extends Handler {
*/
public void doDatabaseCleanup(Account[] accounts, int userId) {
synchronized (mAuthorities) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) Log.w(TAG, "Updating for new accounts...");
+ if (DEBUG) Log.v(TAG, "Updating for new accounts...");
SparseArray<AuthorityInfo> removing = new SparseArray<AuthorityInfo>();
Iterator<AccountInfo> accIt = mAccounts.values().iterator();
while (accIt.hasNext()) {
@@ -945,8 +955,8 @@ public class SyncStorageEngine extends Handler {
if (!ArrayUtils.contains(accounts, acc.accountAndUser.account)
&& acc.accountAndUser.userId == userId) {
// This account no longer exists...
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.w(TAG, "Account removed: " + acc.accountAndUser);
+ if (DEBUG) {
+ Log.v(TAG, "Account removed: " + acc.accountAndUser);
}
for (AuthorityInfo auth : acc.authorities.values()) {
removing.put(auth.ident, auth);
@@ -992,7 +1002,7 @@ public class SyncStorageEngine extends Handler {
public SyncInfo addActiveSync(SyncManager.ActiveSyncContext activeSyncContext) {
final SyncInfo syncInfo;
synchronized (mAuthorities) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
Log.v(TAG, "setActiveSync: account="
+ activeSyncContext.mSyncOperation.account
+ " auth=" + activeSyncContext.mSyncOperation.authority
@@ -1020,7 +1030,7 @@ public class SyncStorageEngine extends Handler {
*/
public void removeActiveSync(SyncInfo syncInfo, int userId) {
synchronized (mAuthorities) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
Log.v(TAG, "removeActiveSync: account=" + syncInfo.account
+ " user=" + userId
+ " auth=" + syncInfo.authority);
@@ -1045,7 +1055,7 @@ public class SyncStorageEngine extends Handler {
long now, int source, boolean initialization) {
long id;
synchronized (mAuthorities) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
Log.v(TAG, "insertStartSyncEvent: account=" + accountName + "user=" + userId
+ " auth=" + authorityName + " source=" + source);
}
@@ -1067,7 +1077,7 @@ public class SyncStorageEngine extends Handler {
mSyncHistory.remove(mSyncHistory.size()-1);
}
id = item.historyId;
- if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "returning historyId " + id);
+ if (DEBUG) Log.v(TAG, "returning historyId " + id);
}
reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
@@ -1095,7 +1105,7 @@ public class SyncStorageEngine extends Handler {
public void stopSyncEvent(long historyId, long elapsedTime, String resultMessage,
long downstreamActivity, long upstreamActivity) {
synchronized (mAuthorities) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
Log.v(TAG, "stopSyncEvent: historyId=" + historyId);
}
SyncHistoryItem item = null;
@@ -1357,7 +1367,7 @@ public class SyncStorageEngine extends Handler {
AccountInfo accountInfo = mAccounts.get(au);
if (accountInfo == null) {
if (tag != null) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
Log.v(TAG, tag + ": unknown account " + au);
}
}
@@ -1366,7 +1376,7 @@ public class SyncStorageEngine extends Handler {
AuthorityInfo authority = accountInfo.authorities.get(authorityName);
if (authority == null) {
if (tag != null) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
Log.v(TAG, tag + ": unknown authority " + authorityName);
}
}
@@ -1391,7 +1401,7 @@ public class SyncStorageEngine extends Handler {
mNextAuthorityId++;
doWrite = true;
}
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
Log.v(TAG, "created a new AuthorityInfo for " + accountName
+ ", user " + userId
+ ", provider " + authorityName);
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index b0ae5da..b9e432c 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -378,6 +378,7 @@ interface IPackageManager {
VerifierDeviceIdentity getVerifierDeviceIdentity();
boolean isFirstBoot();
+ boolean isOnlyCoreApps();
void setPermissionEnforced(String permission, boolean enforced);
boolean isPermissionEnforced(String permission);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 8ba1988..2c31ea0 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -45,7 +45,7 @@ public abstract class PackageManager {
/**
* This exception is thrown when a given package, application, or component
- * name can not be found.
+ * name cannot be found.
*/
public static class NameNotFoundException extends AndroidException {
public NameNotFoundException() {
@@ -259,7 +259,7 @@ public abstract class PackageManager {
* user has explicitly disabled the application, regardless of what it has
* specified in its manifest. Because this is due to the user's request,
* they may re-enable it if desired through the appropriate system UI. This
- * option currently <strong>can not</strong> be used with
+ * option currently <strong>cannot</strong> be used with
* {@link #setComponentEnabledSetting(ComponentName, int, int)}.
*/
public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3;
@@ -1210,9 +1210,9 @@ public abstract class PackageManager {
* package. If flag GET_UNINSTALLED_PACKAGES is set and if the
* package is not found in the list of installed applications, the
* package information is retrieved from the list of uninstalled
- * applications(which includes installed applications as well as
- * applications with data directory ie applications which had been
- * deleted with DONT_DELTE_DATA flag set).
+ * applications (which includes installed applications as well as
+ * applications with data directory i.e. applications which had been
+ * deleted with {@code DONT_DELETE_DATA} flag set).
* @see #GET_ACTIVITIES
* @see #GET_GIDS
* @see #GET_CONFIGURATIONS
@@ -1253,7 +1253,7 @@ public abstract class PackageManager {
* null if neither are found.
*
* <p>Throws {@link NameNotFoundException} if a package with the given
- * name can not be found on the system.
+ * name cannot be found on the system.
*
* @param packageName The name of the package to inspect.
*
@@ -1268,7 +1268,7 @@ public abstract class PackageManager {
* assigned to a package.
*
* <p>Throws {@link NameNotFoundException} if a package with the given
- * name can not be found on the system.
+ * name cannot be found on the system.
*
* @param packageName The full name (i.e. com.google.apps.contacts) of the
* desired package.
@@ -1283,7 +1283,7 @@ public abstract class PackageManager {
* Retrieve all of the information we know about a particular permission.
*
* <p>Throws {@link NameNotFoundException} if a permission with the given
- * name can not be found on the system.
+ * name cannot be found on the system.
*
* @param name The fully qualified name (i.e. com.google.permission.LOGIN)
* of the permission you are interested in.
@@ -1319,7 +1319,7 @@ public abstract class PackageManager {
* permissions.
*
* <p>Throws {@link NameNotFoundException} if a permission group with the given
- * name can not be found on the system.
+ * name cannot be found on the system.
*
* @param name The fully qualified name (i.e. com.google.permission_group.APPS)
* of the permission you are interested in.
@@ -1348,7 +1348,7 @@ public abstract class PackageManager {
* package/application.
*
* <p>Throws {@link NameNotFoundException} if an application with the given
- * package name can not be found on the system.
+ * package name cannot be found on the system.
*
* @param packageName The full name (i.e. com.google.apps.contacts) of an
* application.
@@ -1364,7 +1364,7 @@ public abstract class PackageManager {
* list of uninstalled applications(which includes
* installed applications as well as applications
* with data directory ie applications which had been
- * deleted with DONT_DELTE_DATA flag set).
+ * deleted with {@code DONT_DELETE_DATA} flag set).
*
* @see #GET_META_DATA
* @see #GET_SHARED_LIBRARY_FILES
@@ -1378,7 +1378,7 @@ public abstract class PackageManager {
* class.
*
* <p>Throws {@link NameNotFoundException} if an activity with the given
- * class name can not be found on the system.
+ * class name cannot be found on the system.
*
* @param component The full component name (i.e.
* com.google.apps.contacts/com.google.apps.contacts.ContactsList) of an Activity
@@ -1401,7 +1401,7 @@ public abstract class PackageManager {
* class.
*
* <p>Throws {@link NameNotFoundException} if a receiver with the given
- * class name can not be found on the system.
+ * class name cannot be found on the system.
*
* @param component The full component name (i.e.
* com.google.apps.calendar/com.google.apps.calendar.CalendarAlarm) of a Receiver
@@ -1424,7 +1424,7 @@ public abstract class PackageManager {
* class.
*
* <p>Throws {@link NameNotFoundException} if a service with the given
- * class name can not be found on the system.
+ * class name cannot be found on the system.
*
* @param component The full component name (i.e.
* com.google.apps.media/com.google.apps.media.BackgroundPlayback) of a Service
@@ -1446,7 +1446,7 @@ public abstract class PackageManager {
* provider class.
*
* <p>Throws {@link NameNotFoundException} if a provider with the given
- * class name can not be found on the system.
+ * class name cannot be found on the system.
*
* @param component The full component name (i.e.
* com.google.providers.media/com.google.providers.media.MediaProvider) of a
@@ -1483,7 +1483,7 @@ public abstract class PackageManager {
* installed on the device. In the unlikely case of there being no
* installed packages, an empty list is returned.
* If flag GET_UNINSTALLED_PACKAGES is set, a list of all
- * applications including those deleted with DONT_DELETE_DATA
+ * applications including those deleted with {@code DONT_DELETE_DATA}
* (partially installed apps with data directory) will be returned.
*
* @see #GET_ACTIVITIES
@@ -1521,7 +1521,7 @@ public abstract class PackageManager {
* installed on the device. In the unlikely case of there being no
* installed packages, an empty list is returned.
* If flag GET_UNINSTALLED_PACKAGES is set, a list of all
- * applications including those deleted with DONT_DELETE_DATA
+ * applications including those deleted with {@code DONT_DELETE_DATA}
* (partially installed apps with data directory) will be returned.
*
* @see #GET_ACTIVITIES
@@ -1726,7 +1726,7 @@ public abstract class PackageManager {
/**
* Return a List of all application packages that are installed on the
* device. If flag GET_UNINSTALLED_PACKAGES has been set, a list of all
- * applications including those deleted with DONT_DELETE_DATA(partially
+ * applications including those deleted with {@code DONT_DELETE_DATA} (partially
* installed apps with data directory) will be returned.
*
* @param flags Additional option flags. Use any combination of
@@ -1737,7 +1737,7 @@ public abstract class PackageManager {
* is installed on the device. In the unlikely case of there being
* no installed applications, an empty list is returned.
* If flag GET_UNINSTALLED_PACKAGES is set, a list of all
- * applications including those deleted with DONT_DELETE_DATA
+ * applications including those deleted with {@code DONT_DELETE_DATA}
* (partially installed apps with data directory) will be returned.
*
* @see #GET_META_DATA
@@ -2043,7 +2043,7 @@ public abstract class PackageManager {
* instrumentation class.
*
* <p>Throws {@link NameNotFoundException} if instrumentation with the
- * given class name can not be found on the system.
+ * given class name cannot be found on the system.
*
* @param className The full name (i.e.
* com.google.apps.contacts.InstrumentList) of an
@@ -2080,8 +2080,8 @@ public abstract class PackageManager {
* icon.
*
* @param packageName The name of the package that this icon is coming from.
- * Can not be null.
- * @param resid The resource identifier of the desired image. Can not be 0.
+ * Cannot be null.
+ * @param resid The resource identifier of the desired image. Cannot be 0.
* @param appInfo Overall information about <var>packageName</var>. This
* may be null, in which case the application information will be retrieved
* for you if needed; if you already have this information around, it can
@@ -2097,7 +2097,7 @@ public abstract class PackageManager {
* Retrieve the icon associated with an activity. Given the full name of
* an activity, retrieves the information about it and calls
* {@link ComponentInfo#loadIcon ComponentInfo.loadIcon()} to return its icon.
- * If the activity can not be found, NameNotFoundException is thrown.
+ * If the activity cannot be found, NameNotFoundException is thrown.
*
* @param activityName Name of the activity whose icon is to be retrieved.
*
@@ -2116,7 +2116,7 @@ public abstract class PackageManager {
* set, this simply returns the result of
* getActivityIcon(intent.getClassName()). Otherwise it resolves the intent's
* component and returns the icon associated with the resolved component.
- * If intent.getClassName() can not be found or the Intent can not be resolved
+ * If intent.getClassName() cannot be found or the Intent cannot be resolved
* to a component, NameNotFoundException is thrown.
*
* @param intent The intent for which you would like to retrieve an icon.
@@ -2155,7 +2155,7 @@ public abstract class PackageManager {
/**
* Retrieve the icon associated with an application. Given the name of the
* application's package, retrieves the information about it and calls
- * getApplicationIcon() to return its icon. If the application can not be
+ * getApplicationIcon() to return its icon. If the application cannot be
* found, NameNotFoundException is thrown.
*
* @param packageName Name of the package whose application icon is to be
@@ -2175,7 +2175,7 @@ public abstract class PackageManager {
* Retrieve the logo associated with an activity. Given the full name of
* an activity, retrieves the information about it and calls
* {@link ComponentInfo#loadLogo ComponentInfo.loadLogo()} to return its logo.
- * If the activity can not be found, NameNotFoundException is thrown.
+ * If the activity cannot be found, NameNotFoundException is thrown.
*
* @param activityName Name of the activity whose logo is to be retrieved.
*
@@ -2195,7 +2195,7 @@ public abstract class PackageManager {
* set, this simply returns the result of
* getActivityLogo(intent.getClassName()). Otherwise it resolves the intent's
* component and returns the logo associated with the resolved component.
- * If intent.getClassName() can not be found or the Intent can not be resolved
+ * If intent.getClassName() cannot be found or the Intent cannot be resolved
* to a component, NameNotFoundException is thrown.
*
* @param intent The intent for which you would like to retrieve a logo.
@@ -2227,7 +2227,7 @@ public abstract class PackageManager {
/**
* Retrieve the logo associated with an application. Given the name of the
* application's package, retrieves the information about it and calls
- * getApplicationLogo() to return its logo. If the application can not be
+ * getApplicationLogo() to return its logo. If the application cannot be
* found, NameNotFoundException is thrown.
*
* @param packageName Name of the package whose application logo is to be
@@ -2251,8 +2251,8 @@ public abstract class PackageManager {
* labels and other text.
*
* @param packageName The name of the package that this text is coming from.
- * Can not be null.
- * @param resid The resource identifier of the desired text. Can not be 0.
+ * Cannot be null.
+ * @param resid The resource identifier of the desired text. Cannot be 0.
* @param appInfo Overall information about <var>packageName</var>. This
* may be null, in which case the application information will be retrieved
* for you if needed; if you already have this information around, it can
@@ -2269,8 +2269,8 @@ public abstract class PackageManager {
* retrieve XML meta data.
*
* @param packageName The name of the package that this xml is coming from.
- * Can not be null.
- * @param resid The resource identifier of the desired xml. Can not be 0.
+ * Cannot be null.
+ * @param resid The resource identifier of the desired xml. Cannot be 0.
* @param appInfo Overall information about <var>packageName</var>. This
* may be null, in which case the application information will be retrieved
* for you if needed; if you already have this information around, it can
@@ -2288,7 +2288,7 @@ public abstract class PackageManager {
*
* @return Returns the label associated with this application, or null if
* it could not be found for any reason.
- * @param info The application to get the label of
+ * @param info The application to get the label of.
*/
public abstract CharSequence getApplicationLabel(ApplicationInfo info);
@@ -2296,7 +2296,7 @@ public abstract class PackageManager {
* Retrieve the resources associated with an activity. Given the full
* name of an activity, retrieves the information about it and calls
* getResources() to return its application's resources. If the activity
- * can not be found, NameNotFoundException is thrown.
+ * cannot be found, NameNotFoundException is thrown.
*
* @param activityName Name of the activity whose resources are to be
* retrieved.
@@ -2327,7 +2327,7 @@ public abstract class PackageManager {
* Retrieve the resources associated with an application. Given the full
* package name of an application, retrieves the information about it and
* calls getResources() to return its application's resources. If the
- * appPackageName can not be found, NameNotFoundException is thrown.
+ * appPackageName cannot be found, NameNotFoundException is thrown.
*
* @param appPackageName Package name of the application whose resources
* are to be retrieved.
@@ -2496,7 +2496,7 @@ public abstract class PackageManager {
* {@link PackageManager#VERIFICATION_REJECT}.
*
* @param id pending package identifier as passed via the
- * {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra
+ * {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra.
* @param verificationCode either {@link PackageManager#VERIFICATION_ALLOW}
* or {@link PackageManager#VERIFICATION_REJECT}.
* @throws SecurityException if the caller does not have the
@@ -2517,7 +2517,7 @@ public abstract class PackageManager {
* will have no effect.
*
* @param id pending package identifier as passed via the
- * {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra
+ * {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra.
* @param verificationCodeAtTimeout either
* {@link PackageManager#VERIFICATION_ALLOW} or
* {@link PackageManager#VERIFICATION_REJECT}. If
@@ -2701,16 +2701,16 @@ public abstract class PackageManager {
/**
* @deprecated This function no longer does anything; it was an old
- * approach to managing preferred activities, which has been superceeded
- * (and conflicts with) the modern activity-based preferences.
+ * approach to managing preferred activities, which has been superseded
+ * by (and conflicts with) the modern activity-based preferences.
*/
@Deprecated
public abstract void addPackageToPreferred(String packageName);
/**
* @deprecated This function no longer does anything; it was an old
- * approach to managing preferred activities, which has been superceeded
- * (and conflicts with) the modern activity-based preferences.
+ * approach to managing preferred activities, which has been superseded
+ * by (and conflicts with) the modern activity-based preferences.
*/
@Deprecated
public abstract void removePackageFromPreferred(String packageName);
@@ -2749,7 +2749,7 @@ public abstract class PackageManager {
/**
* @deprecated This is a protected API that should not have been available
* to third party applications. It is the platform's responsibility for
- * assigning preferred activities and this can not be directly modified.
+ * assigning preferred activities and this cannot be directly modified.
*
* Add a new preferred activity mapping to the system. This will be used
* to automatically select the given activity component when
@@ -2783,7 +2783,7 @@ public abstract class PackageManager {
/**
* @deprecated This is a protected API that should not have been available
* to third party applications. It is the platform's responsibility for
- * assigning preferred activities and this can not be directly modified.
+ * assigning preferred activities and this cannot be directly modified.
*
* Replaces an existing preferred activity mapping to the system, and if that were not present
* adds a new preferred activity. This will be used
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 6def4a1..aaa0917 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -34,6 +34,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.FastXmlSerializer;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -68,6 +69,7 @@ import java.util.Map;
*/
public abstract class RegisteredServicesCache<V> {
private static final String TAG = "PackageManager";
+ private static final boolean DEBUG = false;
public final Context mContext;
private final String mInterfaceName;
@@ -77,15 +79,15 @@ public abstract class RegisteredServicesCache<V> {
private final Object mServicesLock = new Object();
- // @GuardedBy("mServicesLock")
+ @GuardedBy("mServicesLock")
private boolean mPersistentServicesFileDidNotExist;
- // @GuardedBy("mServicesLock")
+ @GuardedBy("mServicesLock")
private final SparseArray<UserServices<V>> mUserServices = new SparseArray<UserServices<V>>();
private static class UserServices<V> {
- // @GuardedBy("mServicesLock")
+ @GuardedBy("mServicesLock")
public final Map<V, Integer> persistentServices = Maps.newHashMap();
- // @GuardedBy("mServicesLock")
+ @GuardedBy("mServicesLock")
public Map<V, ServiceInfo<V>> services = null;
}
@@ -194,7 +196,7 @@ public abstract class RegisteredServicesCache<V> {
}
private void notifyListener(final V type, final int userId, final boolean removed) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
Log.d(TAG, "notifyListener: " + type + " is " + (removed ? "removed" : "added"));
}
RegisteredServicesCacheListener<V> listener;
@@ -290,7 +292,9 @@ public abstract class RegisteredServicesCache<V> {
* given {@link UserHandle}.
*/
private void generateServicesMap(int userId) {
- Slog.d(TAG, "generateServicesMap() for " + userId);
+ if (DEBUG) {
+ Slog.d(TAG, "generateServicesMap() for " + userId);
+ }
final PackageManager pm = mContext.getPackageManager();
final ArrayList<ServiceInfo<V>> serviceInfos = new ArrayList<ServiceInfo<V>>();
@@ -321,6 +325,7 @@ public abstract class RegisteredServicesCache<V> {
}
StringBuilder changes = new StringBuilder();
+ boolean changed = false;
for (ServiceInfo<V> info : serviceInfos) {
// four cases:
// - doesn't exist yet
@@ -333,33 +338,41 @@ public abstract class RegisteredServicesCache<V> {
// - add, notify user that it was added
Integer previousUid = user.persistentServices.get(info.type);
if (previousUid == null) {
- changes.append(" New service added: ").append(info).append("\n");
+ if (DEBUG) {
+ changes.append(" New service added: ").append(info).append("\n");
+ }
+ changed = true;
user.services.put(info.type, info);
user.persistentServices.put(info.type, info.uid);
if (!(mPersistentServicesFileDidNotExist && firstScan)) {
notifyListener(info.type, userId, false /* removed */);
}
} else if (previousUid == info.uid) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
changes.append(" Existing service (nop): ").append(info).append("\n");
}
user.services.put(info.type, info);
} else if (inSystemImage(info.uid)
|| !containsTypeAndUid(serviceInfos, info.type, previousUid)) {
- if (inSystemImage(info.uid)) {
- changes.append(" System service replacing existing: ").append(info)
- .append("\n");
- } else {
- changes.append(" Existing service replacing a removed service: ")
- .append(info).append("\n");
+ if (DEBUG) {
+ if (inSystemImage(info.uid)) {
+ changes.append(" System service replacing existing: ").append(info)
+ .append("\n");
+ } else {
+ changes.append(" Existing service replacing a removed service: ")
+ .append(info).append("\n");
+ }
}
+ changed = true;
user.services.put(info.type, info);
user.persistentServices.put(info.type, info.uid);
notifyListener(info.type, userId, false /* removed */);
} else {
// ignore
- changes.append(" Existing service with new uid ignored: ").append(info)
- .append("\n");
+ if (DEBUG) {
+ changes.append(" Existing service with new uid ignored: ").append(info)
+ .append("\n");
+ }
}
}
@@ -370,22 +383,25 @@ public abstract class RegisteredServicesCache<V> {
}
}
for (V v1 : toBeRemoved) {
+ if (DEBUG) {
+ changes.append(" Service removed: ").append(v1).append("\n");
+ }
+ changed = true;
user.persistentServices.remove(v1);
- changes.append(" Service removed: ").append(v1).append("\n");
notifyListener(v1, userId, true /* removed */);
}
- if (changes.length() > 0) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (DEBUG) {
+ if (changes.length() > 0) {
Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " +
serviceInfos.size() + " services:\n" + changes);
- }
- writePersistentServicesLocked();
- } else {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ } else {
Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " +
serviceInfos.size() + " services unchanged");
}
}
+ if (changed) {
+ writePersistentServicesLocked();
+ }
}
}
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 51a17c1..6166d2c 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -334,8 +334,8 @@ public class SensorEvent {
* </p>
*
* <p>
- * values[2]: Roll, rotation around y-axis (-90 to 90), with positive values
- * when the x-axis moves <b>toward</b> the z-axis.
+ * values[2]: Roll, rotation around the x-axis (-90 to 90)
+ * increasing as the device moves clockwise.
* </p>
* </ul>
*
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index b8ad818..08fba29 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -572,7 +572,10 @@ public abstract class SensorManager {
* are received faster. The value must be one of
* {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
* {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}
- * or, the desired delay between events in microsecond.
+ * or, the desired delay between events in microseconds.
+ * Specifying the delay in microseconds only works from Android
+ * 2.3 (API level 9) onwards. For earlier releases, you must use
+ * one of the {@code SENSOR_DELAY_*} constants.
*
* @return <code>true</code> if the sensor is supported and successfully
* enabled.
@@ -604,7 +607,10 @@ public abstract class SensorManager {
* are received faster. The value must be one of
* {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI},
* {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}.
- * or, the desired delay between events in microsecond.
+ * or, the desired delay between events in microseconds.
+ * Specifying the delay in microseconds only works from Android
+ * 2.3 (API level 9) onwards. For earlier releases, you must use
+ * one of the {@code SENSOR_DELAY_*} constants.
*
* @param handler
* The {@link android.os.Handler Handler} the
diff --git a/core/java/android/hardware/display/WifiDisplay.java b/core/java/android/hardware/display/WifiDisplay.java
index 0138b1c..2fd52b8 100644
--- a/core/java/android/hardware/display/WifiDisplay.java
+++ b/core/java/android/hardware/display/WifiDisplay.java
@@ -107,6 +107,15 @@ public final class WifiDisplay implements Parcelable {
&& Objects.equal(mDeviceAlias, other.mDeviceAlias);
}
+ /**
+ * Returns true if the other display is not null and has the same address as this one.
+ * Can be used to perform identity comparisons on displays ignoring properties
+ * that might change during a connection such as the name or alias.
+ */
+ public boolean hasSameAddress(WifiDisplay other) {
+ return other != null && mDeviceAddress.equals(other.mDeviceAddress);
+ }
+
@Override
public int hashCode() {
// The address on its own should be sufficiently unique for hashing purposes.
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index f07002e..6f1cc94 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -930,11 +930,13 @@ public class InputMethodService extends AbstractInputMethodService {
*/
public void onConfigureWindow(Window win, boolean isFullscreen,
boolean isCandidatesOnly) {
- if (isFullscreen) {
- mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT);
- } else {
- mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT);
+ final int currentHeight = mWindow.getWindow().getAttributes().height;
+ final int newHeight = isFullscreen ? MATCH_PARENT : WRAP_CONTENT;
+ if (mIsInputViewShown && currentHeight != newHeight) {
+ Log.w(TAG, "Window size has been changed. This may cause jankiness of resizing window: "
+ + currentHeight + " -> " + newHeight);
}
+ mWindow.getWindow().setLayout(MATCH_PARENT, newHeight);
}
/**
@@ -997,10 +999,11 @@ public class InputMethodService extends AbstractInputMethodService {
}
void updateExtractFrameVisibility() {
- int vis;
+ final int vis;
if (isFullscreenMode()) {
vis = mExtractViewHidden ? View.INVISIBLE : View.VISIBLE;
- mExtractFrame.setVisibility(View.VISIBLE);
+ // "vis" should be applied for the extract frame as well in the fullscreen mode.
+ mExtractFrame.setVisibility(vis);
} else {
vis = View.VISIBLE;
mExtractFrame.setVisibility(View.GONE);
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
index 874e80a..8dc900e 100644
--- a/core/java/android/net/DhcpStateMachine.java
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -351,6 +351,8 @@ public class DhcpStateMachine extends StateMachine {
DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
if (dhcpAction == DhcpAction.START) {
+ /* Stop any existing DHCP daemon before starting new */
+ NetworkUtils.stopDhcp(mInterfaceName);
if (DBG) Log.d(TAG, "DHCP request on " + mInterfaceName);
success = NetworkUtils.runDhcp(mInterfaceName, dhcpInfoInternal);
mDhcpInfo = dhcpInfoInternal;
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 446bbf0..c757605 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -21,6 +21,7 @@ import android.os.Parcelable;
import android.os.SystemClock;
import android.util.SparseBooleanArray;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Objects;
@@ -190,14 +191,14 @@ public class NetworkStats implements Parcelable {
return clone;
}
- // @VisibleForTesting
+ @VisibleForTesting
public NetworkStats addIfaceValues(
String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
return addValues(
iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L);
}
- // @VisibleForTesting
+ @VisibleForTesting
public NetworkStats addValues(String iface, int uid, int set, int tag, long rxBytes,
long rxPackets, long txBytes, long txPackets, long operations) {
return addValues(new Entry(
@@ -269,7 +270,7 @@ public class NetworkStats implements Parcelable {
return size;
}
- // @VisibleForTesting
+ @VisibleForTesting
public int internalSize() {
return iface.length;
}
@@ -335,7 +336,7 @@ public class NetworkStats implements Parcelable {
* Find first stats index that matches the requested parameters, starting
* search around the hinted index as an optimization.
*/
- // @VisibleForTesting
+ @VisibleForTesting
public int findIndexHinted(String iface, int uid, int set, int tag, int hintIndex) {
for (int offset = 0; offset < size; offset++) {
final int halfOffset = offset / 2;
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index d8e53d5..d3839ad 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -33,6 +33,7 @@ import android.content.res.Resources;
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Objects;
/**
@@ -63,7 +64,7 @@ public class NetworkTemplate implements Parcelable {
private static boolean sForceAllNetworkTypes = false;
- // @VisibleForTesting
+ @VisibleForTesting
public static void forceAllNetworkTypes() {
sForceAllNetworkTypes = true;
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 54f2fe3..9821824 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -18,6 +18,8 @@ package android.os;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.Formatter;
import java.util.List;
import java.util.Map;
@@ -1127,8 +1129,10 @@ public abstract class BatteryStats implements Parcelable {
if (totalTimeMillis != 0) {
sb.append(linePrefix);
formatTimeMs(sb, totalTimeMillis);
- if (name != null) sb.append(name);
- sb.append(' ');
+ if (name != null) {
+ sb.append(name);
+ sb.append(' ');
+ }
sb.append('(');
sb.append(count);
sb.append(" times)");
@@ -1440,8 +1444,21 @@ public abstract class BatteryStats implements Parcelable {
}
}
+ static final class TimerEntry {
+ final String mName;
+ final int mId;
+ final BatteryStats.Timer mTimer;
+ final long mTime;
+ TimerEntry(String name, int id, BatteryStats.Timer timer, long time) {
+ mName = name;
+ mId = id;
+ mTimer = timer;
+ mTime = time;
+ }
+ }
+
@SuppressWarnings("unused")
- public final void dumpLocked(PrintWriter pw, String prefix, int which, int reqUid) {
+ public final void dumpLocked(PrintWriter pw, String prefix, final int which, int reqUid) {
final long rawUptime = SystemClock.uptimeMillis() * 1000;
final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
final long batteryUptime = getBatteryUptime(rawUptime);
@@ -1516,19 +1533,43 @@ public abstract class BatteryStats implements Parcelable {
long txTotal = 0;
long fullWakeLockTimeTotalMicros = 0;
long partialWakeLockTimeTotalMicros = 0;
-
+
+ final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
+ @Override
+ public int compare(TimerEntry lhs, TimerEntry rhs) {
+ long lhsTime = lhs.mTime;
+ long rhsTime = rhs.mTime;
+ if (lhsTime < rhsTime) {
+ return 1;
+ }
+ if (lhsTime > rhsTime) {
+ return -1;
+ }
+ return 0;
+ }
+ };
+
if (reqUid < 0) {
Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
if (kernelWakelocks.size() > 0) {
+ final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
-
+ BatteryStats.Timer timer = ent.getValue();
+ long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
+ if (totalTimeMillis > 0) {
+ timers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
+ }
+ }
+ Collections.sort(timers, timerComparator);
+ for (int i=0; i<timers.size(); i++) {
+ TimerEntry timer = timers.get(i);
String linePrefix = ": ";
sb.setLength(0);
sb.append(prefix);
sb.append(" Kernel Wake lock ");
- sb.append(ent.getKey());
- linePrefix = printWakeLock(sb, ent.getValue(), batteryRealtime, null, which,
- linePrefix);
+ sb.append(timer.mName);
+ linePrefix = printWakeLock(sb, timer.mTimer, batteryRealtime, null,
+ which, linePrefix);
if (!linePrefix.equals(": ")) {
sb.append(" realtime");
// Only print out wake locks that were held
@@ -1537,7 +1578,9 @@ public abstract class BatteryStats implements Parcelable {
}
}
}
-
+
+ final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
+
for (int iu = 0; iu < NU; iu++) {
Uid u = uidStats.valueAt(iu);
rxTotal += u.getTcpBytesReceived(which);
@@ -1557,8 +1600,18 @@ public abstract class BatteryStats implements Parcelable {
Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
if (partialWakeTimer != null) {
- partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTimeLocked(
+ long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
batteryRealtime, which);
+ if (totalTimeMicros > 0) {
+ if (reqUid < 0) {
+ // Only show the ordered list of all wake
+ // locks if the caller is not asking for data
+ // about a specific uid.
+ timers.add(new TimerEntry(ent.getKey(), u.getUid(),
+ partialWakeTimer, totalTimeMicros));
+ }
+ partialWakeLockTimeTotalMicros += totalTimeMicros;
+ }
}
}
}
@@ -1571,7 +1624,7 @@ public abstract class BatteryStats implements Parcelable {
sb.append(prefix);
sb.append(" Total full wakelock time: "); formatTimeMs(sb,
(fullWakeLockTimeTotalMicros + 500) / 1000);
- sb.append(", Total partial waklock time: "); formatTimeMs(sb,
+ sb.append(", Total partial wakelock time: "); formatTimeMs(sb,
(partialWakeLockTimeTotalMicros + 500) / 1000);
pw.println(sb.toString());
@@ -1676,9 +1729,26 @@ public abstract class BatteryStats implements Parcelable {
pw.println(getDischargeAmountScreenOnSinceCharge());
pw.print(prefix); pw.print(" Amount discharged while screen off: ");
pw.println(getDischargeAmountScreenOffSinceCharge());
- pw.println(" ");
+ pw.println();
+ }
+
+ if (timers.size() > 0) {
+ Collections.sort(timers, timerComparator);
+ pw.print(prefix); pw.println(" All partial wake locks:");
+ for (int i=0; i<timers.size(); i++) {
+ TimerEntry timer = timers.get(i);
+ sb.setLength(0);
+ sb.append(" Wake lock #");
+ sb.append(timer.mId);
+ sb.append(" ");
+ sb.append(timer.mName);
+ printWakeLock(sb, timer.mTimer, batteryRealtime, null, which, ": ");
+ sb.append(" realtime");
+ pw.println(sb.toString());
+ }
+ timers.clear();
+ pw.println();
}
-
for (int iu=0; iu<NU; iu++) {
final int uid = uidStats.keyAt(iu);
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 88529f8..1bada67 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -22,6 +22,8 @@ import android.os.storage.StorageVolume;
import android.text.TextUtils;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
import java.io.File;
/**
@@ -47,7 +49,7 @@ public class Environment {
private static final Object sLock = new Object();
- // @GuardedBy("sLock")
+ @GuardedBy("sLock")
private static volatile StorageVolume sPrimaryVolume;
private static StorageVolume getPrimaryVolume() {
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 3e90dfc..ec660ee 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -15,6 +15,9 @@
*/
package android.os;
+
+import dalvik.system.CloseGuard;
+
import java.io.Closeable;
import java.io.File;
import java.io.FileDescriptor;
@@ -31,12 +34,16 @@ import java.net.Socket;
*/
public class ParcelFileDescriptor implements Parcelable, Closeable {
private final FileDescriptor mFileDescriptor;
- private boolean mClosed;
- //this field is to create wrapper for ParcelFileDescriptor using another
- //PartialFileDescriptor but avoid invoking close twice
- //consider ParcelFileDescriptor A(fileDescriptor fd), ParcelFileDescriptor B(A)
- //in this particular case fd.close might be invoked twice.
- private final ParcelFileDescriptor mParcelDescriptor;
+
+ /**
+ * Wrapped {@link ParcelFileDescriptor}, if any. Used to avoid
+ * double-closing {@link #mFileDescriptor}.
+ */
+ private final ParcelFileDescriptor mWrapped;
+
+ private volatile boolean mClosed;
+
+ private final CloseGuard mGuard = CloseGuard.get();
/**
* For use with {@link #open}: if {@link #MODE_CREATE} has been supplied
@@ -289,13 +296,15 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
if (mClosed) {
throw new IllegalStateException("Already closed");
}
- if (mParcelDescriptor != null) {
- int fd = mParcelDescriptor.detachFd();
+ if (mWrapped != null) {
+ int fd = mWrapped.detachFd();
mClosed = true;
+ mGuard.close();
return fd;
}
int fd = getFd();
mClosed = true;
+ mGuard.close();
Parcel.clearFileDescriptor(mFileDescriptor);
return fd;
}
@@ -307,15 +316,16 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
* @throws IOException
* If an error occurs attempting to close this ParcelFileDescriptor.
*/
+ @Override
public void close() throws IOException {
- synchronized (this) {
- if (mClosed) return;
- mClosed = true;
- }
- if (mParcelDescriptor != null) {
+ if (mClosed) return;
+ mClosed = true;
+ mGuard.close();
+
+ if (mWrapped != null) {
// If this is a proxy to another file descriptor, just call through to its
// close method.
- mParcelDescriptor.close();
+ mWrapped.close();
} else {
Parcel.closeFileDescriptor(mFileDescriptor);
}
@@ -374,6 +384,9 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
@Override
protected void finalize() throws Throwable {
+ if (mGuard != null) {
+ mGuard.warnIfOpen();
+ }
try {
if (!mClosed) {
close();
@@ -384,21 +397,22 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
}
public ParcelFileDescriptor(ParcelFileDescriptor descriptor) {
- super();
- mParcelDescriptor = descriptor;
- mFileDescriptor = mParcelDescriptor.mFileDescriptor;
+ mWrapped = descriptor;
+ mFileDescriptor = mWrapped.mFileDescriptor;
+ mGuard.open("close");
}
- /*package */ParcelFileDescriptor(FileDescriptor descriptor) {
- super();
+ /** {@hide} */
+ public ParcelFileDescriptor(FileDescriptor descriptor) {
if (descriptor == null) {
throw new NullPointerException("descriptor must not be null");
}
+ mWrapped = null;
mFileDescriptor = descriptor;
- mParcelDescriptor = null;
+ mGuard.open("close");
}
- /* Parcelable interface */
+ @Override
public int describeContents() {
return Parcelable.CONTENTS_FILE_DESCRIPTOR;
}
@@ -408,6 +422,7 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
* If {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE} is set in flags,
* the file descriptor will be closed after a copy is written to the Parcel.
*/
+ @Override
public void writeToParcel(Parcel out, int flags) {
out.writeFileDescriptor(mFileDescriptor);
if ((flags&PARCELABLE_WRITE_RETURN_VALUE) != 0 && !mClosed) {
@@ -421,12 +436,14 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
public static final Parcelable.Creator<ParcelFileDescriptor> CREATOR
= new Parcelable.Creator<ParcelFileDescriptor>() {
+ @Override
public ParcelFileDescriptor createFromParcel(Parcel in) {
return in.readFileDescriptor();
}
+
+ @Override
public ParcelFileDescriptor[] newArray(int size) {
return new ParcelFileDescriptor[size];
}
};
-
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 4a01113..736762f 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -182,6 +182,8 @@ public final class PowerManager {
* </p><p>
* Since not all devices have proximity sensors, use {@link #isWakeLockLevelSupported}
* to determine whether this wake lock level is supported.
+ * </p><p>
+ * Cannot be used with {@link #ACQUIRE_CAUSES_WAKEUP}.
* </p>
*
* {@hide}
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index ed51818..0ca9183 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -44,6 +44,7 @@ public final class Trace {
public static final long TRACE_TAG_AUDIO = 1L << 8;
public static final long TRACE_TAG_VIDEO = 1L << 9;
public static final long TRACE_TAG_CAMERA = 1L << 10;
+ private static final long TRACE_TAG_NOT_READY = 1L << 63;
public static final int TRACE_FLAGS_START_BIT = 1;
public static final String[] TRACE_TAGS = {
@@ -53,11 +54,8 @@ public final class Trace {
public static final String PROPERTY_TRACE_TAG_ENABLEFLAGS = "debug.atrace.tags.enableflags";
- // This works as a "not ready" flag because TRACE_TAG_ALWAYS is always set.
- private static final long TRACE_FLAGS_NOT_READY = 0;
-
// Must be volatile to avoid word tearing.
- private static volatile long sEnabledTags = TRACE_FLAGS_NOT_READY;
+ private static volatile long sEnabledTags = TRACE_TAG_NOT_READY;
private static native long nativeGetEnabledTags();
private static native void nativeTraceCounter(long tag, String name, int value);
@@ -99,7 +97,7 @@ public final class Trace {
*/
private static long cacheEnabledTags() {
long tags = nativeGetEnabledTags();
- if (tags == TRACE_FLAGS_NOT_READY) {
+ if (tags == TRACE_TAG_NOT_READY) {
Log.w(TAG, "Unexpected value from nativeGetEnabledTags: " + tags);
// keep going
}
@@ -115,7 +113,7 @@ public final class Trace {
*/
public static boolean isTagEnabled(long traceTag) {
long tags = sEnabledTags;
- if (tags == TRACE_FLAGS_NOT_READY) {
+ if (tags == TRACE_TAG_NOT_READY) {
tags = cacheEnabledTags();
}
return (tags & traceTag) != 0;
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index af6e88e9..0fa5799 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -106,16 +106,13 @@ public final class CalendarContract {
* {@link Activity#RESULT_OK} or {@link Activity#RESULT_CANCELED} to
* acknowledge whether the action was handled or not.
*
- * The custom app should have an intent-filter like the following
+ * The custom app should have an intent filter like the following:
* <pre>
- * {@code
- * <intent-filter>
- * <action android:name="android.provider.calendar.action.HANDLE_CUSTOM_EVENT" />
- * <category android:name="android.intent.category.DEFAULT" />
- * <data android:mimeType="vnd.android.cursor.item/event" />
- * </intent-filter>
- * }
- * </pre>
+ * &lt;intent-filter&gt;
+ * &lt;action android:name="android.provider.calendar.action.HANDLE_CUSTOM_EVENT" /&gt;
+ * &lt;category android:name="android.intent.category.DEFAULT" /&gt;
+ * &lt;data android:mimeType="vnd.android.cursor.item/event" /&gt;
+ * &lt;/intent-filter&gt;</pre>
* <p>
* Input: {@link Intent#getData} has the event URI. The extra
* {@link #EXTRA_EVENT_BEGIN_TIME} has the start time of the instance. The
@@ -123,7 +120,7 @@ public final class CalendarContract {
* {@link EventsColumns#CUSTOM_APP_URI}.
* <p>
* Output: {@link Activity#RESULT_OK} if this was handled; otherwise
- * {@link Activity#RESULT_CANCELED}
+ * {@link Activity#RESULT_CANCELED}.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_HANDLE_CUSTOM_EVENT =
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 8f54a38..e3053be 100755
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1359,7 +1359,7 @@ public final class ContactsContract {
* status definitions. Automatically computed as the highest presence of all
* constituent raw contacts. The provider may choose not to store this value
* in persistent storage. The expectation is that presence status will be
- * updated on a regular basic.</td>
+ * updated on a regular basis.</td>
* </tr>
* <tr>
* <td>String</td>
@@ -2326,7 +2326,7 @@ public final class ContactsContract {
* parameters. The latter approach is preferable, especially when you can reuse the
* URI:
* <pre>
- * Uri rawContactUri = RawContacts.URI.buildUpon()
+ * Uri rawContactUri = RawContacts.CONTENT_URI.buildUpon()
* .appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName)
* .appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType)
* .build();
@@ -4131,7 +4131,7 @@ public final class ContactsContract {
* all IM rows. See {@link StatusUpdates} for individual status definitions.
* The provider may choose not to store this value
* in persistent storage. The expectation is that presence status will be
- * updated on a regular basic.
+ * updated on a regular basis.
* </td>
* </tr>
* <tr>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b94f0b9..4dbc4b4 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -626,6 +626,21 @@ public final class Settings {
public static final String ACTION_NFCSHARING_SETTINGS =
"android.settings.NFCSHARING_SETTINGS";
+ /**
+ * Activity Action: Show Daydream settings.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ * @see android.service.dreams.DreamService
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
+
// End of Intent actions for Settings
/**
@@ -4281,6 +4296,13 @@ public final class Settings {
public static final String POWER_SOUNDS_ENABLED = "power_sounds_enabled";
/**
+ * URI for the "wireless charging started" sound.
+ * @hide
+ */
+ public static final String WIRELESS_CHARGING_STARTED_SOUND =
+ "wireless_charging_started_sound";
+
+ /**
* Whether we keep the device on while the device is plugged in.
* Supported values are:
* <ul>
@@ -5315,6 +5337,12 @@ public final class Settings {
public static final String DOCK_AUDIO_MEDIA_ENABLED = "dock_audio_media_enabled";
/**
+ * Persisted safe headphone volume management state by AudioService
+ * @hide
+ */
+ public static final String AUDIO_SAFE_VOLUME_STATE = "audio_safe_volume_state";
+
+ /**
* Settings to backup. This is here so that it's in the same place as the settings
* keys and easy to update.
*
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index 4a21374..46f2723 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -92,7 +92,7 @@ public class SearchManagerService extends ISearchManager.Stub {
Searchables searchables = mSearchables.get(userId);
if (searchables == null) {
- Log.i(TAG, "Building list of searchable activities for userId=" + userId);
+ //Log.i(TAG, "Building list of searchable activities for userId=" + userId);
searchables = new Searchables(mContext, userId);
searchables.buildSearchableList();
mSearchables.append(userId, searchables);
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 1060bd8..bcce61d 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -607,6 +607,30 @@ public class DateUtils
}
/**
+ * Return given duration in a human-friendly format. For example, "4
+ * minutes" or "1 second". Returns only largest meaningful unit of time,
+ * from seconds up to hours.
+ *
+ * @hide
+ */
+ public static CharSequence formatDuration(long millis) {
+ final Resources res = Resources.getSystem();
+ if (millis >= HOUR_IN_MILLIS) {
+ final int hours = (int) ((millis + 1800000) / HOUR_IN_MILLIS);
+ return res.getQuantityString(
+ com.android.internal.R.plurals.duration_hours, hours, hours);
+ } else if (millis >= MINUTE_IN_MILLIS) {
+ final int minutes = (int) ((millis + 30000) / MINUTE_IN_MILLIS);
+ return res.getQuantityString(
+ com.android.internal.R.plurals.duration_minutes, minutes, minutes);
+ } else {
+ final int seconds = (int) ((millis + 500) / SECOND_IN_MILLIS);
+ return res.getQuantityString(
+ com.android.internal.R.plurals.duration_seconds, seconds, seconds);
+ }
+ }
+
+ /**
* Formats an elapsed time in the form "MM:SS" or "H:MM:SS"
* for display on the call-in-progress screen.
* @param elapsedSeconds the elapsed time in seconds.
diff --git a/core/java/android/util/AttributeSet.java b/core/java/android/util/AttributeSet.java
index 470526c..74942ba 100644
--- a/core/java/android/util/AttributeSet.java
+++ b/core/java/android/util/AttributeSet.java
@@ -151,7 +151,7 @@ public interface AttributeSet {
* Return the value of 'attribute' as a resource identifier.
*
* <p>Note that this is different than {@link #getAttributeNameResource}
- * in that it returns a the value contained in this attribute as a
+ * in that it returns the value contained in this attribute as a
* resource identifier (i.e., a value originally of the form
* "@package:type/resource"); the other method returns a resource
* identifier that identifies the name of the attribute.
@@ -230,7 +230,7 @@ public interface AttributeSet {
* Return the value of attribute at 'index' as a resource identifier.
*
* <p>Note that this is different than {@link #getAttributeNameResource}
- * in that it returns a the value contained in this attribute as a
+ * in that it returns the value contained in this attribute as a
* resource identifier (i.e., a value originally of the form
* "@package:type/resource"); the other method returns a resource
* identifier that identifies the name of the attribute.
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 85e4b9d..e856501 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -232,19 +232,32 @@ public class DisplayMetrics {
* @return True if the display metrics are equal.
*/
public boolean equals(DisplayMetrics other) {
+ return equalsPhysical(other)
+ && scaledDensity == other.scaledDensity
+ && noncompatScaledDensity == other.noncompatScaledDensity;
+ }
+
+ /**
+ * Returns true if the physical aspects of the two display metrics
+ * are equal. This ignores the scaled density, which is a logical
+ * attribute based on the current desired font size.
+ *
+ * @param other The display metrics with which to compare.
+ * @return True if the display metrics are equal.
+ * @hide
+ */
+ public boolean equalsPhysical(DisplayMetrics other) {
return other != null
&& widthPixels == other.widthPixels
&& heightPixels == other.heightPixels
&& density == other.density
&& densityDpi == other.densityDpi
- && scaledDensity == other.scaledDensity
&& xdpi == other.xdpi
&& ydpi == other.ydpi
&& noncompatWidthPixels == other.noncompatWidthPixels
&& noncompatHeightPixels == other.noncompatHeightPixels
&& noncompatDensity == other.noncompatDensity
&& noncompatDensityDpi == other.noncompatDensityDpi
- && noncompatScaledDensity == other.noncompatScaledDensity
&& noncompatXdpi == other.noncompatXdpi
&& noncompatYdpi == other.noncompatYdpi;
}
diff --git a/core/java/android/util/IntProperty.java b/core/java/android/util/IntProperty.java
index 459d6b2..17977ca 100644
--- a/core/java/android/util/IntProperty.java
+++ b/core/java/android/util/IntProperty.java
@@ -42,7 +42,7 @@ public abstract class IntProperty<T> extends Property<T, Integer> {
@Override
final public void set(T object, Integer value) {
- set(object, value.intValue());
+ setValue(object, value.intValue());
}
} \ No newline at end of file
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index f3841d5..305fd5c 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -285,6 +285,16 @@ public final class DisplayInfo implements Parcelable {
getMetricsWithSize(outMetrics, cih, logicalWidth, logicalHeight);
}
+ public int getNaturalWidth() {
+ return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
+ logicalWidth : logicalHeight;
+ }
+
+ public int getNaturalHeight() {
+ return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
+ logicalHeight : logicalWidth;
+ }
+
private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfoHolder cih,
int width, int height) {
outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi;
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 1c613245..5b7a5af 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -1304,17 +1304,11 @@ public abstract class HardwareRenderer {
}
}
- if ((status & DisplayList.STATUS_INVOKE) != 0) {
- scheduleFunctors(attachInfo, true);
- }
- }
-
- private void scheduleFunctors(View.AttachInfo attachInfo, boolean delayed) {
- mFunctorsRunnable.attachInfo = attachInfo;
- if (!attachInfo.mHandler.hasCallbacks(mFunctorsRunnable)) {
- // delay the functor callback by a few ms so it isn't polled constantly
- attachInfo.mHandler.postDelayed(mFunctorsRunnable,
- delayed ? FUNCTOR_PROCESS_DELAY : 0);
+ if ((status & DisplayList.STATUS_INVOKE) != 0 ||
+ attachInfo.mHandler.hasCallbacks(mFunctorsRunnable)) {
+ attachInfo.mHandler.removeCallbacks(mFunctorsRunnable);
+ mFunctorsRunnable.attachInfo = attachInfo;
+ attachInfo.mHandler.postDelayed(mFunctorsRunnable, FUNCTOR_PROCESS_DELAY);
}
}
@@ -1329,7 +1323,9 @@ public abstract class HardwareRenderer {
boolean attachFunctor(View.AttachInfo attachInfo, int functor) {
if (mCanvas != null) {
mCanvas.attachFunctor(functor);
- scheduleFunctors(attachInfo, false);
+ mFunctorsRunnable.attachInfo = attachInfo;
+ attachInfo.mHandler.removeCallbacks(mFunctorsRunnable);
+ attachInfo.mHandler.postDelayed(mFunctorsRunnable, 0);
return true;
}
return false;
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 0fe2a8e..2b6cbcf 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -74,7 +74,7 @@ interface IWindowManager
void setEventDispatching(boolean enabled);
void addWindowToken(IBinder token, int type);
void removeWindowToken(IBinder token);
- void addAppToken(int addPos, IApplicationToken token,
+ void addAppToken(int addPos, int userId, IApplicationToken token,
int groupId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked);
void setAppGroupId(IBinder token, int groupId);
void setAppOrientation(IApplicationToken token, int requestedOrientation);
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index ee3f5d8..51c5c7b 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -259,6 +259,8 @@ public class ScaleGestureDetector {
mInputEventConsistencyVerifier.onTouchEvent(event, 0);
}
+ mCurrTime = event.getEventTime();
+
final int action = event.getActionMasked();
final boolean streamComplete = action == MotionEvent.ACTION_UP ||
@@ -341,6 +343,7 @@ public class ScaleGestureDetector {
mPrevSpanX = mCurrSpanX = spanX;
mPrevSpanY = mCurrSpanY = spanY;
mPrevSpan = mCurrSpan = span;
+ mPrevTime = mCurrTime;
mInProgress = mListener.onScaleBegin(this);
}
@@ -359,6 +362,7 @@ public class ScaleGestureDetector {
mPrevSpanX = mCurrSpanX;
mPrevSpanY = mCurrSpanY;
mPrevSpan = mCurrSpan;
+ mPrevTime = mCurrTime;
}
}
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 550a740..0a81a71 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -225,6 +225,9 @@ public class Surface implements Parcelable {
// non compatibility mode.
private Matrix mCompatibleMatrix;
+ private int mWidth;
+ private int mHeight;
+
private native void nativeCreate(SurfaceSession session, String name,
int w, int h, int format, int flags)
throws OutOfResourcesException;
@@ -330,6 +333,8 @@ public class Surface implements Parcelable {
checkHeadless();
mName = name;
+ mWidth = w;
+ mHeight = h;
nativeCreate(session, name, w, h, format, flags);
mCloseGuard.open("release");
@@ -538,7 +543,7 @@ public class Surface implements Parcelable {
/** @hide */
public void setPosition(int x, int y) {
- nativeSetPosition((float)x, (float)y);
+ nativeSetPosition(x, y);
}
/** @hide */
@@ -548,10 +553,22 @@ public class Surface implements Parcelable {
/** @hide */
public void setSize(int w, int h) {
+ mWidth = w;
+ mHeight = h;
nativeSetSize(w, h);
}
/** @hide */
+ public int getWidth() {
+ return mWidth;
+ }
+
+ /** @hide */
+ public int getHeight() {
+ return mHeight;
+ }
+
+ /** @hide */
public void hide() {
nativeSetFlags(SURFACE_HIDDEN, SURFACE_HIDDEN);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ef50353..cf61599 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -11856,8 +11856,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mCurrentAnimation = null;
- resetRtlProperties();
- onRtlPropertiesChanged(LAYOUT_DIRECTION_DEFAULT);
resetAccessibilityStateChanged();
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 00723f3..dbbcde6 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3620,8 +3620,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
childHasTransientStateChanged(view, false);
}
- view.resetRtlProperties();
-
onViewRemoved(view);
needGlobalAttributesUpdate(false);
@@ -5372,21 +5370,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @hide
*/
@Override
- public void resetRtlProperties() {
- super.resetRtlProperties();
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.isLayoutDirectionInherited()) {
- child.resetRtlProperties();
- }
- }
- }
-
- /**
- * @hide
- */
- @Override
public void resetResolvedLayoutDirection() {
super.resetResolvedLayoutDirection();
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index d7c7f46..001d020 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -302,6 +302,7 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
lp.type = LayoutParams.TYPE_VOLUME_OVERLAY;
lp.width = LayoutParams.WRAP_CONTENT;
lp.height = LayoutParams.WRAP_CONTENT;
+ lp.privateFlags |= LayoutParams.PRIVATE_FLAG_FORCE_SHOW_NAV_BAR;
window.setAttributes(lp);
window.addFlags(LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 3b31ff6..6a67d8b 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -946,6 +946,13 @@ public interface WindowManager extends ViewManager {
public static final int PRIVATE_FLAG_SHOW_FOR_ALL_USERS = 0x00000010;
/**
+ * Special flag for the volume overlay: force the window manager out of "hide nav bar"
+ * mode while the window is on screen.
+ *
+ * {@hide} */
+ public static final int PRIVATE_FLAG_FORCE_SHOW_NAV_BAR = 0x00000020;
+
+ /**
* Control flags that are private to the platform.
* @hide
*/
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 421a324..452ad1b 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -248,6 +248,15 @@ public abstract class CompoundButton extends Button implements Checkable {
return padding;
}
+ /**
+ * @hide
+ */
+ @Override
+ public int getHorizontalOffsetForDrawables() {
+ final Drawable buttonDrawable = mButtonDrawable;
+ return (buttonDrawable != null) ? buttonDrawable.getIntrinsicWidth() : 0;
+ }
+
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index b1a44c5..30d022c 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -36,6 +36,8 @@ import android.graphics.drawable.Drawable;
import android.inputmethodservice.ExtractEditText;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
import android.os.SystemClock;
import android.provider.Settings;
import android.text.DynamicLayout;
@@ -187,6 +189,8 @@ public class Editor {
private TextView mTextView;
+ private final UserDictionaryListener mUserDictionaryListener = new UserDictionaryListener();
+
Editor(TextView textView) {
mTextView = textView;
}
@@ -291,6 +295,7 @@ public class Editor {
mErrorWasChanged = true;
if (mError == null) {
+ setErrorIcon(null);
if (mErrorPopup != null) {
if (mErrorPopup.isShowing()) {
mErrorPopup.dismiss();
@@ -299,21 +304,24 @@ public class Editor {
mErrorPopup = null;
}
- setErrorIcon(null);
- } else if (mTextView.isFocused()) {
- showError();
+ } else {
setErrorIcon(icon);
+ if (mTextView.isFocused()) {
+ showError();
+ }
}
}
private void setErrorIcon(Drawable icon) {
- final Drawables dr = mTextView.mDrawables;
- if (dr != null) {
- mTextView.setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon,
- dr.mDrawableBottom);
- } else {
- mTextView.setCompoundDrawables(null, null, icon, null);
+ Drawables dr = mTextView.mDrawables;
+ if (dr == null) {
+ mTextView.mDrawables = dr = new Drawables();
}
+ dr.setErrorDrawable(icon, mTextView);
+
+ mTextView.resetResolvedDrawables();
+ mTextView.invalidate();
+ mTextView.requestLayout();
}
private void hideError() {
@@ -321,15 +329,13 @@ public class Editor {
if (mErrorPopup.isShowing()) {
mErrorPopup.dismiss();
}
-
- setErrorIcon(null);
}
mShowErrorAfterAttach = false;
}
/**
- * Returns the Y offset to make the pointy top of the error point
+ * Returns the X offset to make the pointy top of the error point
* at the middle of the error icon.
*/
private int getErrorX() {
@@ -340,8 +346,23 @@ public class Editor {
final float scale = mTextView.getResources().getDisplayMetrics().density;
final Drawables dr = mTextView.mDrawables;
- return mTextView.getWidth() - mErrorPopup.getWidth() - mTextView.getPaddingRight() -
- (dr != null ? dr.mDrawableSizeRight : 0) / 2 + (int) (25 * scale + 0.5f);
+
+ final int layoutDirection = mTextView.getLayoutDirection();
+ int errorX;
+ int offset;
+ switch (layoutDirection) {
+ default:
+ case View.LAYOUT_DIRECTION_LTR:
+ offset = - (dr != null ? dr.mDrawableSizeRight : 0) / 2 + (int) (25 * scale + 0.5f);
+ errorX = mTextView.getWidth() - mErrorPopup.getWidth() -
+ mTextView.getPaddingRight() + offset;
+ break;
+ case View.LAYOUT_DIRECTION_RTL:
+ offset = (dr != null ? dr.mDrawableSizeLeft : 0) / 2 - (int) (25 * scale + 0.5f);
+ errorX = mTextView.getPaddingLeft() + offset;
+ break;
+ }
+ return errorX;
}
/**
@@ -358,16 +379,27 @@ public class Editor {
mTextView.getCompoundPaddingBottom() - compoundPaddingTop;
final Drawables dr = mTextView.mDrawables;
- int icontop = compoundPaddingTop +
- (vspace - (dr != null ? dr.mDrawableHeightRight : 0)) / 2;
+
+ final int layoutDirection = mTextView.getLayoutDirection();
+ int height;
+ switch (layoutDirection) {
+ default:
+ case View.LAYOUT_DIRECTION_LTR:
+ height = (dr != null ? dr.mDrawableHeightRight : 0);
+ break;
+ case View.LAYOUT_DIRECTION_RTL:
+ height = (dr != null ? dr.mDrawableHeightLeft : 0);
+ break;
+ }
+
+ int icontop = compoundPaddingTop + (vspace - height) / 2;
/*
* The "2" is the distance between the point and the top edge
* of the background.
*/
final float scale = mTextView.getResources().getDisplayMetrics().density;
- return icontop + (dr != null ? dr.mDrawableHeightRight : 0) - mTextView.getHeight() -
- (int) (2 * scale + 0.5f);
+ return icontop + height - mTextView.getHeight() - (int) (2 * scale + 0.5f);
}
void createInputContentTypeIfNeeded() {
@@ -2574,6 +2606,11 @@ public class Editor {
Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT);
intent.putExtra("word", originalText);
intent.putExtra("locale", mTextView.getTextServicesLocale().toString());
+ // Put a listener to replace the original text with a word which the user
+ // modified in a user dictionary dialog.
+ mUserDictionaryListener.waitForUserDictionaryAdded(
+ mTextView, originalText, spanStart, spanEnd);
+ intent.putExtra("listener", new Messenger(mUserDictionaryListener));
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
mTextView.getContext().startActivity(intent);
// There is no way to know if the word was indeed added. Re-check.
@@ -3726,7 +3763,7 @@ public class Editor {
super(v, width, height);
mView = v;
// Make sure the TextView has a background set as it will be used the first time it is
- // shown and positionned. Initialized with below background, which should have
+ // shown and positioned. Initialized with below background, which should have
// dimensions identical to the above version for this to work (and is more likely).
mPopupInlineErrorBackgroundId = getResourceId(mPopupInlineErrorBackgroundId,
com.android.internal.R.styleable.Theme_errorMessageBackground);
@@ -3792,4 +3829,65 @@ public class Editor {
boolean mContentChanged;
int mChangedStart, mChangedEnd, mChangedDelta;
}
+
+ /**
+ * @hide
+ */
+ public static class UserDictionaryListener extends Handler {
+ public TextView mTextView;
+ public String mOriginalWord;
+ public int mWordStart;
+ public int mWordEnd;
+
+ public void waitForUserDictionaryAdded(
+ TextView tv, String originalWord, int spanStart, int spanEnd) {
+ mTextView = tv;
+ mOriginalWord = originalWord;
+ mWordStart = spanStart;
+ mWordEnd = spanEnd;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case 0: /* CODE_WORD_ADDED */
+ case 2: /* CODE_ALREADY_PRESENT */
+ if (!(msg.obj instanceof Bundle)) {
+ Log.w(TAG, "Illegal message. Abort handling onUserDictionaryAdded.");
+ return;
+ }
+ final Bundle bundle = (Bundle)msg.obj;
+ final String originalWord = bundle.getString("originalWord");
+ final String addedWord = bundle.getString("word");
+ onUserDictionaryAdded(originalWord, addedWord);
+ return;
+ default:
+ return;
+ }
+ }
+
+ private void onUserDictionaryAdded(String originalWord, String addedWord) {
+ if (TextUtils.isEmpty(mOriginalWord) || TextUtils.isEmpty(addedWord)) {
+ return;
+ }
+ if (mWordStart < 0 || mWordEnd >= mTextView.length()) {
+ return;
+ }
+ if (!mOriginalWord.equals(originalWord)) {
+ return;
+ }
+ if (originalWord.equals(addedWord)) {
+ return;
+ }
+ final Editable editable = (Editable) mTextView.getText();
+ final String currentWord = editable.toString().substring(mWordStart, mWordEnd);
+ if (!currentWord.equals(originalWord)) {
+ return;
+ }
+ mTextView.replaceText_internal(mWordStart, mWordEnd, addedWord);
+ // Move cursor at the end of the replaced word
+ final int newCursorPosition = mWordStart + addedWord.length();
+ mTextView.setCursorPosition_internal(newCursorPosition, newCursorPosition);
+ }
+ }
}
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index e52e84d..27fda24 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -369,10 +369,10 @@ public class RelativeLayout extends ViewGroup {
int width = 0;
int height = 0;
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+ final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+ final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+ final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
// Record our dimensions if they are known;
if (widthMode != MeasureSpec.UNSPECIFIED) {
@@ -416,6 +416,42 @@ public class RelativeLayout extends ViewGroup {
View[] views = mSortedHorizontalChildren;
int count = views.length;
+
+ // We need to know our size for doing the correct computation of positioning in RTL mode
+ if (isLayoutRtl() && (myWidth == -1 || isWrapContentWidth)) {
+ int w = getPaddingStart() + getPaddingEnd();
+ final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ for (int i = 0; i < count; i++) {
+ View child = views[i];
+ if (child.getVisibility() != GONE) {
+ LayoutParams params = (LayoutParams) child.getLayoutParams();
+ // Would be similar to a call to measureChildHorizontal(child, params, -1, myHeight)
+ // but we cannot change for now the behavior of measureChildHorizontal() for
+ // taking care or a "-1" for "mywidth" so use here our own version of that code.
+ int childHeightMeasureSpec;
+ if (params.width == LayoutParams.MATCH_PARENT) {
+ childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.EXACTLY);
+ } else {
+ childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.AT_MOST);
+ }
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+
+ w += child.getMeasuredWidth();
+ w += params.leftMargin + params.rightMargin;
+ }
+ }
+ if (myWidth == -1) {
+ // Easy case: "myWidth" was undefined before so use the width we have just computed
+ myWidth = w;
+ } else {
+ // "myWidth" was defined before, so take the min of it and the computed width if it
+ // is a non null one
+ if (w > 0) {
+ myWidth = Math.min(myWidth, w);
+ }
+ }
+ }
+
for (int i = 0; i < count; i++) {
View child = views[i];
if (child.getVisibility() != GONE) {
@@ -924,7 +960,7 @@ public class RelativeLayout extends ViewGroup {
// Find the first non-GONE view up the chain
while (v.getVisibility() == View.GONE) {
- rules = ((LayoutParams) v.getLayoutParams()).getRules();
+ rules = ((LayoutParams) v.getLayoutParams()).getRules(v.getLayoutDirection());
node = mGraph.mKeyNodes.get((rules[relation]));
if (node == null) return null;
v = node.view;
@@ -975,7 +1011,7 @@ public class RelativeLayout extends ViewGroup {
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// The layout has actually already been performed and the positions
// cached. Apply the cached values to the children.
- int count = getChildCount();
+ final int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index e481702..aeee111 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
+
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
@@ -29,9 +30,10 @@ import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.Log;
-import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.MeasureSpec;
@@ -40,6 +42,7 @@ import android.widget.RemoteViews.OnClickHandler;
import com.android.internal.widget.IRemoteViewsAdapterConnection;
import com.android.internal.widget.IRemoteViewsFactory;
+import com.android.internal.widget.LockPatternUtils;
/**
* An adapter to a RemoteViewsService which fetches and caches RemoteViews
@@ -87,13 +90,15 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
private Handler mMainQueue;
// We cache the FixedSizeRemoteViewsCaches across orientation. These are the related data
- // structures;
- private static final HashMap<Pair<Intent.FilterComparison, Integer>, FixedSizeRemoteViewsCache>
- sCachedRemoteViewsCaches = new HashMap<Pair<Intent.FilterComparison, Integer>,
+ // structures;
+ private static final HashMap<RemoteViewsCacheKey,
+ FixedSizeRemoteViewsCache> sCachedRemoteViewsCaches
+ = new HashMap<RemoteViewsCacheKey,
FixedSizeRemoteViewsCache>();
- private static final HashMap<Pair<Intent.FilterComparison, Integer>, Runnable>
- sRemoteViewsCacheRemoveRunnables = new HashMap<Pair<Intent.FilterComparison, Integer>,
- Runnable>();
+ private static final HashMap<RemoteViewsCacheKey, Runnable>
+ sRemoteViewsCacheRemoveRunnables
+ = new HashMap<RemoteViewsCacheKey, Runnable>();
+
private static HandlerThread sCacheRemovalThread;
private static Handler sCacheRemovalQueue;
@@ -106,6 +111,8 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
// construction (happens when we have a cached FixedSizeRemoteViewsCache).
private boolean mDataReady = false;
+ int mUserId;
+
/**
* An interface for the RemoteAdapter to notify other classes when adapters
* are actually connected to/disconnected from their actual services.
@@ -146,8 +153,16 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
public synchronized void bind(Context context, int appWidgetId, Intent intent) {
if (!mIsConnecting) {
try {
+ RemoteViewsAdapter adapter;
final AppWidgetManager mgr = AppWidgetManager.getInstance(context);
- mgr.bindRemoteViewsService(appWidgetId, intent, asBinder());
+ if (Process.myUid() == Process.SYSTEM_UID
+ && (adapter = mAdapter.get()) != null) {
+ mgr.bindRemoteViewsService(appWidgetId, intent, asBinder(),
+ new UserHandle(adapter.mUserId));
+ } else {
+ mgr.bindRemoteViewsService(appWidgetId, intent, asBinder(),
+ Process.myUserHandle());
+ }
mIsConnecting = true;
} catch (Exception e) {
Log.e("RemoteViewsAdapterServiceConnection", "bind(): " + e.getMessage());
@@ -159,8 +174,15 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
public synchronized void unbind(Context context, int appWidgetId, Intent intent) {
try {
+ RemoteViewsAdapter adapter;
final AppWidgetManager mgr = AppWidgetManager.getInstance(context);
- mgr.unbindRemoteViewsService(appWidgetId, intent);
+ if (Process.myUid() == Process.SYSTEM_UID
+ && (adapter = mAdapter.get()) != null) {
+ mgr.unbindRemoteViewsService(appWidgetId, intent,
+ new UserHandle(adapter.mUserId));
+ } else {
+ mgr.unbindRemoteViewsService(appWidgetId, intent, Process.myUserHandle());
+ }
mIsConnecting = false;
} catch (Exception e) {
Log.e("RemoteViewsAdapterServiceConnection", "unbind(): " + e.getMessage());
@@ -296,9 +318,13 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
*/
private class RemoteViewsFrameLayoutRefSet {
private HashMap<Integer, LinkedList<RemoteViewsFrameLayout>> mReferences;
+ private HashMap<RemoteViewsFrameLayout, LinkedList<RemoteViewsFrameLayout>>
+ mViewToLinkedList;
public RemoteViewsFrameLayoutRefSet() {
mReferences = new HashMap<Integer, LinkedList<RemoteViewsFrameLayout>>();
+ mViewToLinkedList =
+ new HashMap<RemoteViewsFrameLayout, LinkedList<RemoteViewsFrameLayout>>();
}
/**
@@ -315,6 +341,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
refs = new LinkedList<RemoteViewsFrameLayout>();
mReferences.put(pos, refs);
}
+ mViewToLinkedList.put(layout, refs);
// Add the references to the list
refs.add(layout);
@@ -333,21 +360,34 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
final LinkedList<RemoteViewsFrameLayout> refs = mReferences.get(pos);
for (final RemoteViewsFrameLayout ref : refs) {
ref.onRemoteViewsLoaded(view, mRemoteViewsOnClickHandler);
+ if (mViewToLinkedList.containsKey(ref)) {
+ mViewToLinkedList.remove(ref);
+ }
}
refs.clear();
-
// Remove this set from the original mapping
mReferences.remove(pos);
}
}
/**
+ * We need to remove views from this set if they have been recycled by the AdapterView.
+ */
+ public void removeView(RemoteViewsFrameLayout rvfl) {
+ if (mViewToLinkedList.containsKey(rvfl)) {
+ mViewToLinkedList.get(rvfl).remove(rvfl);
+ mViewToLinkedList.remove(rvfl);
+ }
+ }
+
+ /**
* Removes all references to all RemoteViewsFrameLayouts returned by the adapter.
*/
public void clear() {
// We currently just clear the references, and leave all the previous layouts returned
// in their default state of the loading view.
mReferences.clear();
+ mViewToLinkedList.clear();
}
}
@@ -751,6 +791,33 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
}
}
+ static class RemoteViewsCacheKey {
+ final Intent.FilterComparison filter;
+ final int widgetId;
+ final int userId;
+
+ RemoteViewsCacheKey(Intent.FilterComparison filter, int widgetId, int userId) {
+ this.filter = filter;
+ this.widgetId = widgetId;
+ this.userId = userId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof RemoteViewsCacheKey)) {
+ return false;
+ }
+ RemoteViewsCacheKey other = (RemoteViewsCacheKey) o;
+ return other.filter.equals(filter) && other.widgetId == widgetId
+ && other.userId == userId;
+ }
+
+ @Override
+ public int hashCode() {
+ return (filter == null ? 0 : filter.hashCode()) ^ (widgetId << 2) ^ (userId << 10);
+ }
+ }
+
public RemoteViewsAdapter(Context context, Intent intent, RemoteAdapterConnectionCallback callback) {
mContext = context;
mIntent = intent;
@@ -761,6 +828,11 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
}
mRequestedViews = new RemoteViewsFrameLayoutRefSet();
+ if (Process.myUid() == Process.SYSTEM_UID) {
+ mUserId = new LockPatternUtils(context).getCurrentUser();
+ } else {
+ mUserId = UserHandle.myUserId();
+ }
// Strip the previously injected app widget id from service intent
if (intent.hasExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID)) {
intent.removeExtra(RemoteViews.EXTRA_REMOTEADAPTER_APPWIDGET_ID);
@@ -782,8 +854,8 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
mCallback = new WeakReference<RemoteAdapterConnectionCallback>(callback);
mServiceConnection = new RemoteViewsAdapterServiceConnection(this);
- Pair<Intent.FilterComparison, Integer> key = new Pair<Intent.FilterComparison, Integer>
- (new Intent.FilterComparison(mIntent), mAppWidgetId);
+ RemoteViewsCacheKey key = new RemoteViewsCacheKey(new Intent.FilterComparison(mIntent),
+ mAppWidgetId, mUserId);
synchronized(sCachedRemoteViewsCaches) {
if (sCachedRemoteViewsCaches.containsKey(key)) {
@@ -824,8 +896,8 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
}
public void saveRemoteViewsCache() {
- final Pair<Intent.FilterComparison, Integer> key = new Pair<Intent.FilterComparison,
- Integer> (new Intent.FilterComparison(mIntent), mAppWidgetId);
+ final RemoteViewsCacheKey key = new RemoteViewsCacheKey(
+ new Intent.FilterComparison(mIntent), mAppWidgetId, mUserId);
synchronized(sCachedRemoteViewsCaches) {
// If we already have a remove runnable posted for this key, remove it.
@@ -947,6 +1019,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
long itemId = 0;
try {
remoteViews = factory.getViewAt(position);
+ remoteViews.setUser(new UserHandle(mUserId));
itemId = factory.getItemId(position);
} catch (RemoteException e) {
Log.e(TAG, "Error in updateRemoteViews(" + position + "): " + e.getMessage());
@@ -1079,6 +1152,10 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
boolean isConnected = mServiceConnection.isConnected();
boolean hasNewItems = false;
+ if (convertView != null && convertView instanceof RemoteViewsFrameLayout) {
+ mRequestedViews.removeView((RemoteViewsFrameLayout) convertView);
+ }
+
if (!isInCache && !isConnected) {
// Requesting bind service will trigger a super.notifyDataSetChanged(), which will
// in turn trigger another request to getView()
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index 1ae77b3..02b7030 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -39,31 +39,26 @@ import com.android.internal.R;
* <p>
* Here is how to use the action provider with custom backing file in a {@link MenuItem}:
* </p>
- * <p>
* <pre>
- * <code>
- * // In Activity#onCreateOptionsMenu
- * public boolean onCreateOptionsMenu(Menu menu) {
- * // Get the menu item.
- * MenuItem menuItem = menu.findItem(R.id.my_menu_item);
- * // Get the provider and hold onto it to set/change the share intent.
- * mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
- * // Set history different from the default before getting the action
- * // view since a call to {@link MenuItem#getActionView() MenuItem.getActionView()} calls
- * // {@link ActionProvider#onCreateActionView()} which uses the backing file name. Omit this
- * // line if using the default share history file is desired.
- * mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
- * . . .
- * }
+ * // In Activity#onCreateOptionsMenu
+ * public boolean onCreateOptionsMenu(Menu menu) {
+ * // Get the menu item.
+ * MenuItem menuItem = menu.findItem(R.id.my_menu_item);
+ * // Get the provider and hold onto it to set/change the share intent.
+ * mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
+ * // Set history different from the default before getting the action
+ * // view since a call to {@link MenuItem#getActionView() MenuItem.getActionView()} calls
+ * // {@link ActionProvider#onCreateActionView()} which uses the backing file name. Omit this
+ * // line if using the default share history file is desired.
+ * mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
+ * . . .
+ * }
*
- * // Somewhere in the application.
- * public void doShare(Intent shareIntent) {
- * // When you want to share set the share intent.
- * mShareActionProvider.setShareIntent(shareIntent);
- * }
- * </pre>
- * </code>
- * </p>
+ * // Somewhere in the application.
+ * public void doShare(Intent shareIntent) {
+ * // When you want to share set the share intent.
+ * mShareActionProvider.setShareIntent(shareIntent);
+ * }</pre>
* <p>
* <strong>Note:</strong> While the sample snippet demonstrates how to use this provider
* in the context of a menu item, the use of the provider is not limited to menu items.
@@ -247,9 +242,9 @@ public class ShareActionProvider extends ActionProvider {
* call {@link android.app.Activity#invalidateOptionsMenu()} to recreate the
* action view. You should <strong>not</strong> call
* {@link android.app.Activity#invalidateOptionsMenu()} from
- * {@link android.app.Activity#onCreateOptionsMenu(Menu)}."
- * <p>
- * <code>
+ * {@link android.app.Activity#onCreateOptionsMenu(Menu)}.
+ * </p>
+ * <pre>
* private void doShare(Intent intent) {
* if (IMAGE.equals(intent.getMimeType())) {
* mShareActionProvider.setHistoryFileName(SHARE_IMAGE_HISTORY_FILE_NAME);
@@ -258,9 +253,7 @@ public class ShareActionProvider extends ActionProvider {
* }
* mShareActionProvider.setIntent(intent);
* invalidateOptionsMenu();
- * }
- * <code>
- *
+ * }</pre>
* @param shareHistoryFile The share history file name.
*/
public void setShareHistoryFileName(String shareHistoryFile) {
@@ -271,16 +264,11 @@ public class ShareActionProvider extends ActionProvider {
/**
* Sets an intent with information about the share action. Here is a
* sample for constructing a share intent:
- * <p>
* <pre>
- * <code>
- * Intent shareIntent = new Intent(Intent.ACTION_SEND);
- * shareIntent.setType("image/*");
- * Uri uri = Uri.fromFile(new File(getFilesDir(), "foo.jpg"));
- * shareIntent.putExtra(Intent.EXTRA_STREAM, uri.toString());
- * </pre>
- * </code>
- * </p>
+ * Intent shareIntent = new Intent(Intent.ACTION_SEND);
+ * shareIntent.setType("image/*");
+ * Uri uri = Uri.fromFile(new File(getFilesDir(), "foo.jpg"));
+ * shareIntent.putExtra(Intent.EXTRA_STREAM, uri.toString());</pre>
*
* @param shareIntent The share intent.
*
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5d90400..7c1b959 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -142,6 +142,13 @@ import java.util.concurrent.locks.ReentrantLock;
* view for editing.
*
* <p>
+ * To allow users to copy some or all of the TextView's value and paste it somewhere else, set the
+ * XML attribute {@link android.R.styleable#TextView_textIsSelectable
+ * android:textIsSelectable} to "true" or call
+ * {@link #setTextIsSelectable setTextIsSelectable(true)}. The {@code textIsSelectable} flag
+ * allows users to make selection gestures in the TextView, which in turn triggers the system's
+ * built-in copy/paste controls.
+ * <p>
* <b>XML attributes</b>
* <p>
* See {@link android.R.styleable#TextView TextView Attributes},
@@ -284,15 +291,144 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
private TextUtils.TruncateAt mEllipsize;
static class Drawables {
+ final static int DRAWABLE_NONE = -1;
+ final static int DRAWABLE_RIGHT = 0;
+ final static int DRAWABLE_LEFT = 1;
+
final Rect mCompoundRect = new Rect();
+
Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight,
- mDrawableStart, mDrawableEnd;
+ mDrawableStart, mDrawableEnd, mDrawableError, mDrawableTemp;
+
int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight,
- mDrawableSizeStart, mDrawableSizeEnd;
+ mDrawableSizeStart, mDrawableSizeEnd, mDrawableSizeError, mDrawableSizeTemp;
+
int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight,
- mDrawableHeightStart, mDrawableHeightEnd;
+ mDrawableHeightStart, mDrawableHeightEnd, mDrawableHeightError, mDrawableHeightTemp;
+
int mDrawablePadding;
+
+ int mDrawableSaved = DRAWABLE_NONE;
+
+ public void resolveWithLayoutDirection(int layoutDirection) {
+ switch(layoutDirection) {
+ case LAYOUT_DIRECTION_RTL:
+ if (mDrawableStart != null) {
+ mDrawableRight = mDrawableStart;
+
+ mDrawableSizeRight = mDrawableSizeStart;
+ mDrawableHeightRight = mDrawableHeightStart;
+ }
+ if (mDrawableEnd != null) {
+ mDrawableLeft = mDrawableEnd;
+
+ mDrawableSizeLeft = mDrawableSizeEnd;
+ mDrawableHeightLeft = mDrawableHeightEnd;
+ }
+ break;
+
+ case LAYOUT_DIRECTION_LTR:
+ default:
+ if (mDrawableStart != null) {
+ mDrawableLeft = mDrawableStart;
+
+ mDrawableSizeLeft = mDrawableSizeStart;
+ mDrawableHeightLeft = mDrawableHeightStart;
+ }
+ if (mDrawableEnd != null) {
+ mDrawableRight = mDrawableEnd;
+
+ mDrawableSizeRight = mDrawableSizeEnd;
+ mDrawableHeightRight = mDrawableHeightEnd;
+ }
+ break;
+ }
+ applyErrorDrawableIfNeeded(layoutDirection);
+ updateDrawablesLayoutDirection(layoutDirection);
+ }
+
+ private void updateDrawablesLayoutDirection(int layoutDirection) {
+ if (mDrawableLeft != null) {
+ mDrawableLeft.setLayoutDirection(layoutDirection);
+ }
+ if (mDrawableRight != null) {
+ mDrawableRight.setLayoutDirection(layoutDirection);
+ }
+ if (mDrawableTop != null) {
+ mDrawableTop.setLayoutDirection(layoutDirection);
+ }
+ if (mDrawableBottom != null) {
+ mDrawableBottom.setLayoutDirection(layoutDirection);
+ }
+ }
+
+ public void setErrorDrawable(Drawable dr, TextView tv) {
+ if (mDrawableError != dr && mDrawableError != null) {
+ mDrawableError.setCallback(null);
+ }
+ mDrawableError = dr;
+
+ final Rect compoundRect = mCompoundRect;
+ int[] state = tv.getDrawableState();
+
+ if (mDrawableError != null) {
+ mDrawableError.setState(state);
+ mDrawableError.copyBounds(compoundRect);
+ mDrawableError.setCallback(tv);
+ mDrawableSizeError = compoundRect.width();
+ mDrawableHeightError = compoundRect.height();
+ } else {
+ mDrawableSizeError = mDrawableHeightError = 0;
+ }
+ }
+
+ private void applyErrorDrawableIfNeeded(int layoutDirection) {
+ // first restore the initial state if needed
+ switch (mDrawableSaved) {
+ case DRAWABLE_LEFT:
+ mDrawableLeft = mDrawableTemp;
+ mDrawableSizeLeft = mDrawableSizeTemp;
+ mDrawableHeightLeft = mDrawableHeightTemp;
+ break;
+ case DRAWABLE_RIGHT:
+ mDrawableRight = mDrawableTemp;
+ mDrawableSizeRight = mDrawableSizeTemp;
+ mDrawableHeightRight = mDrawableHeightTemp;
+ break;
+ case DRAWABLE_NONE:
+ default:
+ }
+ // then, if needed, assign the Error drawable to the correct location
+ if (mDrawableError != null) {
+ switch(layoutDirection) {
+ case LAYOUT_DIRECTION_RTL:
+ mDrawableSaved = DRAWABLE_LEFT;
+
+ mDrawableTemp = mDrawableLeft;
+ mDrawableSizeTemp = mDrawableSizeLeft;
+ mDrawableHeightTemp = mDrawableHeightLeft;
+
+ mDrawableLeft = mDrawableError;
+ mDrawableSizeLeft = mDrawableSizeError;
+ mDrawableHeightLeft = mDrawableHeightError;
+ break;
+ case LAYOUT_DIRECTION_LTR:
+ default:
+ mDrawableSaved = DRAWABLE_RIGHT;
+
+ mDrawableTemp = mDrawableRight;
+ mDrawableSizeTemp = mDrawableSizeRight;
+ mDrawableHeightTemp = mDrawableHeightRight;
+
+ mDrawableRight = mDrawableError;
+ mDrawableSizeRight = mDrawableSizeError;
+ mDrawableHeightRight = mDrawableHeightError;
+ break;
+ }
+ }
+ }
}
+
Drawables mDrawables;
private CharWrapper mCharWrapper;
@@ -4609,17 +4745,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
- * When a TextView is used to display a useful piece of information to the user (such as a
- * contact's address), it should be made selectable, so that the user can select and copy this
- * content.
- *
- * Use {@link #setTextIsSelectable(boolean)} or the
- * {@link android.R.styleable#TextView_textIsSelectable} XML attribute to make this TextView
- * selectable (text is not selectable by default).
*
- * Note that this method simply returns the state of this flag. Although this flag has to be set
- * in order to select text in non-editable TextView, the content of an {@link EditText} can
- * always be selected, independently of the value of this flag.
+ * Returns the state of the {@code textIsSelectable} flag (See
+ * {@link #setTextIsSelectable setTextIsSelectable()}). Although you have to set this flag
+ * to allow users to select and copy text in a non-editable TextView, the content of an
+ * {@link EditText} can always be selected, independently of the value of this flag.
+ * <p>
*
* @return True if the text displayed in this TextView can be selected by the user.
*
@@ -4630,16 +4761,28 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
- * Sets whether or not (default) the content of this view is selectable by the user.
- *
- * Note that this methods affect the {@link #setFocusable(boolean)},
- * {@link #setFocusableInTouchMode(boolean)} {@link #setClickable(boolean)} and
- * {@link #setLongClickable(boolean)} states and you may want to restore these if they were
- * customized.
- *
- * See {@link #isTextSelectable} for details.
- *
- * @param selectable Whether or not the content of this TextView should be selectable.
+ * Sets whether the content of this view is selectable by the user. The default is
+ * {@code false}, meaning that the content is not selectable.
+ * <p>
+ * When you use a TextView to display a useful piece of information to the user (such as a
+ * contact's address), make it selectable, so that the user can select and copy its
+ * content. You can also use set the XML attribute
+ * {@link android.R.styleable#TextView_textIsSelectable} to "true".
+ * <p>
+ * When you call this method to set the value of {@code textIsSelectable}, it sets
+ * the flags {@code focusable}, {@code focusableInTouchMode}, {@code clickable},
+ * and {@code longClickable} to the same value. These flags correspond to the attributes
+ * {@link android.R.styleable#View_focusable android:focusable},
+ * {@link android.R.styleable#View_focusableInTouchMode android:focusableInTouchMode},
+ * {@link android.R.styleable#View_clickable android:clickable}, and
+ * {@link android.R.styleable#View_longClickable android:longClickable}. To restore any of these
+ * flags to a state you had set previously, call one or more of the following methods:
+ * {@link #setFocusable(boolean) setFocusable()},
+ * {@link #setFocusableInTouchMode(boolean) setFocusableInTouchMode()},
+ * {@link #setClickable(boolean) setClickable()} or
+ * {@link #setLongClickable(boolean) setLongClickable()}.
+ *
+ * @param selectable Whether the content of this TextView should be selectable.
*/
public void setTextIsSelectable(boolean selectable) {
if (!selectable && mEditor == null) return; // false is default value with no edit data
@@ -4734,6 +4877,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return highlight;
}
+ /**
+ * @hide
+ */
+ public int getHorizontalOffsetForDrawables() {
+ return 0;
+ }
+
@Override
protected void onDraw(Canvas canvas) {
restartMarqueeIfNeeded();
@@ -4751,6 +4901,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
final int left = mLeft;
final int bottom = mBottom;
final int top = mTop;
+ final boolean isLayoutRtl = isLayoutRtl();
+ final int offset = getHorizontalOffsetForDrawables();
+ final int leftOffset = isLayoutRtl ? 0 : offset;
+ final int rightOffset = isLayoutRtl ? offset : 0 ;
final Drawables dr = mDrawables;
if (dr != null) {
@@ -4766,7 +4920,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// Make sure to update invalidateDrawable() when changing this code.
if (dr.mDrawableLeft != null) {
canvas.save();
- canvas.translate(scrollX + mPaddingLeft,
+ canvas.translate(scrollX + mPaddingLeft + leftOffset,
scrollY + compoundPaddingTop +
(vspace - dr.mDrawableHeightLeft) / 2);
dr.mDrawableLeft.draw(canvas);
@@ -4777,7 +4931,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// Make sure to update invalidateDrawable() when changing this code.
if (dr.mDrawableRight != null) {
canvas.save();
- canvas.translate(scrollX + right - left - mPaddingRight - dr.mDrawableSizeRight,
+ canvas.translate(scrollX + right - left - mPaddingRight
+ - dr.mDrawableSizeRight - rightOffset,
scrollY + compoundPaddingTop + (vspace - dr.mDrawableHeightRight) / 2);
dr.mDrawableRight.draw(canvas);
canvas.restore();
@@ -4862,8 +5017,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText);
- final boolean isLayoutRtl = isLayoutRtl();
-
final int layoutDirection = getLayoutDirection();
final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
@@ -8229,9 +8382,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
TextDirectionHeuristic getTextDirectionHeuristic() {
if (hasPasswordTransformationMethod()) {
- // TODO: take care of the content direction to show the password text and dots justified
- // to the left or to the right
- return TextDirectionHeuristics.LOCALE;
+ // passwords fields should be LTR
+ return TextDirectionHeuristics.LTR;
}
// Always need to resolve layout direction first
@@ -8264,63 +8416,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return;
}
mLastLayoutDirection = layoutDirection;
- // No drawable to resolve
- if (mDrawables == null) {
- return;
- }
- // No relative drawable to resolve
- if (mDrawables.mDrawableStart == null && mDrawables.mDrawableEnd == null) {
- return;
- }
- Drawables dr = mDrawables;
- switch(layoutDirection) {
- case LAYOUT_DIRECTION_RTL:
- if (dr.mDrawableStart != null) {
- dr.mDrawableRight = dr.mDrawableStart;
-
- dr.mDrawableSizeRight = dr.mDrawableSizeStart;
- dr.mDrawableHeightRight = dr.mDrawableHeightStart;
- }
- if (dr.mDrawableEnd != null) {
- dr.mDrawableLeft = dr.mDrawableEnd;
-
- dr.mDrawableSizeLeft = dr.mDrawableSizeEnd;
- dr.mDrawableHeightLeft = dr.mDrawableHeightEnd;
- }
- break;
-
- case LAYOUT_DIRECTION_LTR:
- default:
- if (dr.mDrawableStart != null) {
- dr.mDrawableLeft = dr.mDrawableStart;
-
- dr.mDrawableSizeLeft = dr.mDrawableSizeStart;
- dr.mDrawableHeightLeft = dr.mDrawableHeightStart;
- }
- if (dr.mDrawableEnd != null) {
- dr.mDrawableRight = dr.mDrawableEnd;
-
- dr.mDrawableSizeRight = dr.mDrawableSizeEnd;
- dr.mDrawableHeightRight = dr.mDrawableHeightEnd;
- }
- break;
- }
- updateDrawablesLayoutDirection(dr, layoutDirection);
- }
-
- private void updateDrawablesLayoutDirection(Drawables dr, int layoutDirection) {
- if (dr.mDrawableLeft != null) {
- dr.mDrawableLeft.setLayoutDirection(layoutDirection);
- }
- if (dr.mDrawableRight != null) {
- dr.mDrawableRight.setLayoutDirection(layoutDirection);
- }
- if (dr.mDrawableTop != null) {
- dr.mDrawableTop.setLayoutDirection(layoutDirection);
- }
- if (dr.mDrawableBottom != null) {
- dr.mDrawableBottom.setLayoutDirection(layoutDirection);
+ // Resolve drawables
+ if (mDrawables != null) {
+ mDrawables.resolveWithLayoutDirection(layoutDirection);
}
}
@@ -8328,6 +8427,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @hide
*/
protected void resetResolvedDrawables() {
+ super.resetResolvedDrawables();
mLastLayoutDirection = -1;
}
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 485bd37..1d85126 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -374,8 +374,11 @@ public class Toast {
// remove the old view if necessary
handleHide();
mView = mNextView;
- mWM = (WindowManager)mView.getContext().getApplicationContext()
- .getSystemService(Context.WINDOW_SERVICE);
+ Context context = mView.getContext().getApplicationContext();
+ if (context == null) {
+ context = mView.getContext();
+ }
+ mWM = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
// We can resolve the Gravity here by using the Locale for getting
// the layout direction
final Configuration config = mView.getContext().getResources().getConfiguration();
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 7c8196d..329b0df 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -54,7 +54,6 @@ public class VideoView extends SurfaceView implements MediaPlayerControl {
// settable by the client
private Uri mUri;
private Map<String, String> mHeaders;
- private int mDuration;
// all possible internal states
private static final int STATE_ERROR = -1;
@@ -229,7 +228,6 @@ public class VideoView extends SurfaceView implements MediaPlayerControl {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnPreparedListener(mPreparedListener);
mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
- mDuration = -1;
mMediaPlayer.setOnCompletionListener(mCompletionListener);
mMediaPlayer.setOnErrorListener(mErrorListener);
mMediaPlayer.setOnInfoListener(mOnInfoListener);
@@ -608,17 +606,12 @@ public class VideoView extends SurfaceView implements MediaPlayerControl {
openVideo();
}
- // cache duration as mDuration for faster access
public int getDuration() {
if (isInPlaybackState()) {
- if (mDuration > 0) {
- return mDuration;
- }
- mDuration = mMediaPlayer.getDuration();
- return mDuration;
+ return mMediaPlayer.getDuration();
}
- mDuration = -1;
- return mDuration;
+
+ return -1;
}
public int getCurrentPosition() {
diff --git a/core/java/com/android/internal/annotations/GuardedBy.java b/core/java/com/android/internal/annotations/GuardedBy.java
new file mode 100644
index 0000000..fc61945
--- /dev/null
+++ b/core/java/com/android/internal/annotations/GuardedBy.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation type used to mark a method or field that can only be accessed when
+ * holding the referenced lock.
+ */
+@Target({ ElementType.FIELD, ElementType.METHOD })
+@Retention(RetentionPolicy.CLASS)
+public @interface GuardedBy {
+ String value();
+}
diff --git a/core/java/com/android/internal/annotations/Immutable.java b/core/java/com/android/internal/annotations/Immutable.java
new file mode 100644
index 0000000..b424275
--- /dev/null
+++ b/core/java/com/android/internal/annotations/Immutable.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation type used to mark a class which is immutable.
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.CLASS)
+public @interface Immutable {
+}
diff --git a/core/java/com/android/internal/annotations/VisibleForTesting.java b/core/java/com/android/internal/annotations/VisibleForTesting.java
new file mode 100644
index 0000000..bc3121c
--- /dev/null
+++ b/core/java/com/android/internal/annotations/VisibleForTesting.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Denotes that the class, method or field has its visibility relaxed so
+ * that unit tests can access it.
+ * <p/>
+ * The <code>visibility</code> argument can be used to specific what the original
+ * visibility should have been if it had not been made public or package-private for testing.
+ * The default is to consider the element private.
+ */
+@Retention(RetentionPolicy.SOURCE)
+public @interface VisibleForTesting {
+ /**
+ * Intended visibility if the element had not been made public or package-private for
+ * testing.
+ */
+ enum Visibility {
+ /** The element should be considered protected. */
+ PROTECTED,
+ /** The element should be considered package-private. */
+ PACKAGE,
+ /** The element should be considered private. */
+ PRIVATE
+ }
+
+ /**
+ * Intended visibility if the element had not been made public or package-private for testing.
+ * If not specified, one should assume the element originally intended to be private.
+ */
+ Visibility visibility() default Visibility.PRIVATE;
+}
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index a95fe2b..6233522 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -810,6 +810,11 @@ public class ActionBarImpl extends ActionBar {
return mThemedContext;
}
+ @Override
+ public boolean isTitleTruncated() {
+ return mActionView != null && mActionView.isTitleTruncated();
+ }
+
/**
* @hide
*/
diff --git a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
index 386f387..2bc80ff 100644
--- a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
+++ b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
@@ -136,13 +136,14 @@ public class MediaRouteChooserDialogFragment extends DialogFragment {
if (mRouter == null) return;
final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes);
- mVolumeIcon.setImageResource(
+ mVolumeIcon.setImageResource(selectedRoute == null ||
selectedRoute.getPlaybackType() == RouteInfo.PLAYBACK_TYPE_LOCAL ?
R.drawable.ic_audio_vol : R.drawable.ic_media_route_on_holo_dark);
mIgnoreSliderVolumeChanges = true;
- if (selectedRoute.getVolumeHandling() == RouteInfo.PLAYBACK_VOLUME_FIXED) {
+ if (selectedRoute == null ||
+ selectedRoute.getVolumeHandling() == RouteInfo.PLAYBACK_VOLUME_FIXED) {
// Disable the slider and show it at max volume.
mVolumeSlider.setMax(1);
mVolumeSlider.setProgress(1);
@@ -160,7 +161,8 @@ public class MediaRouteChooserDialogFragment extends DialogFragment {
if (mIgnoreSliderVolumeChanges) return;
final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes);
- if (selectedRoute.getVolumeHandling() == RouteInfo.PLAYBACK_VOLUME_VARIABLE) {
+ if (selectedRoute != null &&
+ selectedRoute.getVolumeHandling() == RouteInfo.PLAYBACK_VOLUME_VARIABLE) {
final int maxVolume = selectedRoute.getVolumeMax();
newValue = Math.max(0, Math.min(newValue, maxVolume));
selectedRoute.requestSetVolume(newValue);
@@ -652,14 +654,19 @@ public class MediaRouteChooserDialogFragment extends DialogFragment {
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mVolumeSlider.isEnabled()) {
- mRouter.getSelectedRoute(mRouteTypes).requestUpdateVolume(-1);
- return true;
+ final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes);
+ if (selectedRoute != null) {
+ selectedRoute.requestUpdateVolume(-1);
+ return true;
+ }
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mVolumeSlider.isEnabled()) {
- mRouter.getSelectedRoute(mRouteTypes).requestUpdateVolume(1);
- return true;
- } else {
- return super.onKeyDown(keyCode, event);
+ final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes);
+ if (selectedRoute != null) {
+ mRouter.getSelectedRoute(mRouteTypes).requestUpdateVolume(1);
+ return true;
+ }
}
+ return super.onKeyDown(keyCode, event);
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index cfb16fa..e685e63 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -32,12 +32,16 @@ interface IAppWidgetService {
//
int[] startListening(IAppWidgetHost host, String packageName, int hostId,
out List<RemoteViews> updatedViews);
+ int[] startListeningAsUser(IAppWidgetHost host, String packageName, int hostId,
+ out List<RemoteViews> updatedViews, int userId);
void stopListening(int hostId);
+ void stopListeningAsUser(int hostId, int userId);
int allocateAppWidgetId(String packageName, int hostId);
void deleteAppWidgetId(int appWidgetId);
void deleteHost(int hostId);
void deleteAllHosts();
RemoteViews getAppWidgetViews(int appWidgetId);
+ int[] getAppWidgetIdsForHost(int hostId);
//
// for AppWidgetManager
@@ -48,15 +52,15 @@ interface IAppWidgetService {
void partiallyUpdateAppWidgetIds(in int[] appWidgetIds, in RemoteViews views);
void updateAppWidgetProvider(in ComponentName provider, in RemoteViews views);
void notifyAppWidgetViewDataChanged(in int[] appWidgetIds, int viewId);
- List<AppWidgetProviderInfo> getInstalledProviders();
+ List<AppWidgetProviderInfo> getInstalledProviders(int categoryFilter);
AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId);
boolean hasBindAppWidgetPermission(in String packageName);
void setBindAppWidgetPermission(in String packageName, in boolean permission);
void bindAppWidgetId(int appWidgetId, in ComponentName provider, in Bundle options);
boolean bindAppWidgetIdIfAllowed(
in String packageName, int appWidgetId, in ComponentName provider, in Bundle options);
- void bindRemoteViewsService(int appWidgetId, in Intent intent, in IBinder connection);
- void unbindRemoteViewsService(int appWidgetId, in Intent intent);
+ void bindRemoteViewsService(int appWidgetId, in Intent intent, in IBinder connection, int userId);
+ void unbindRemoteViewsService(int appWidgetId, in Intent intent, int userId);
int[] getAppWidgetIds(in ComponentName provider);
}
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index c5e7d9d..1a4835b 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -51,7 +51,7 @@ public class PackageHelper {
public static final int RECOMMEND_FAILED_INVALID_URI = -6;
public static final int RECOMMEND_FAILED_VERSION_DOWNGRADE = -7;
- private static final boolean localLOGV = true;
+ private static final boolean localLOGV = false;
private static final String TAG = "PackageHelper";
// App installation location settings values
public static final int APP_INSTALL_AUTO = 0;
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index 8b222f0..c517a68 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -25,6 +25,7 @@ import android.net.NetworkStats;
import android.os.StrictMode;
import android.os.SystemClock;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ProcFileReader;
import java.io.File;
@@ -53,7 +54,7 @@ public class NetworkStatsFactory {
this(new File("/proc/"));
}
- // @VisibleForTesting
+ @VisibleForTesting
public NetworkStatsFactory(File procRoot) {
mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
diff --git a/core/java/com/android/internal/util/LocalLog.java b/core/java/com/android/internal/util/LocalLog.java
new file mode 100644
index 0000000..f0e6171
--- /dev/null
+++ b/core/java/com/android/internal/util/LocalLog.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+import android.util.Slog;
+
+/**
+ * Helper class for logging serious issues, which also keeps a small
+ * snapshot of the logged events that can be printed later, such as part
+ * of a system service's dumpsys output.
+ * @hide
+ */
+public class LocalLog {
+ private final String mTag;
+ private final int mMaxLines = 20;
+ private final ArrayList<String> mLines = new ArrayList<String>(mMaxLines);
+
+ public LocalLog(String tag) {
+ mTag = tag;
+ }
+
+ public void w(String msg) {
+ synchronized (mLines) {
+ Slog.w(mTag, msg);
+ if (mLines.size() >= mMaxLines) {
+ mLines.remove(0);
+ }
+ mLines.add(msg);
+ }
+ }
+
+ public boolean dump(PrintWriter pw, String header, String prefix) {
+ synchronized (mLines) {
+ if (mLines.size() <= 0) {
+ return false;
+ }
+ if (header != null) {
+ pw.println(header);
+ }
+ for (int i=0; i<mLines.size(); i++) {
+ if (prefix != null) {
+ pw.print(prefix);
+ }
+ pw.println(mLines.get(i));
+ }
+ return true;
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 28c6bc9..534e034 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -40,6 +40,7 @@ import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.Layout;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
@@ -49,7 +50,6 @@ import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
-import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
@@ -83,7 +83,8 @@ public class ActionBarView extends AbsActionBarView {
ActionBar.DISPLAY_USE_LOGO |
ActionBar.DISPLAY_HOME_AS_UP |
ActionBar.DISPLAY_SHOW_CUSTOM |
- ActionBar.DISPLAY_SHOW_TITLE;
+ ActionBar.DISPLAY_SHOW_TITLE |
+ ActionBar.DISPLAY_TITLE_MULTIPLE_LINES;
private static final int DEFAULT_CUSTOM_GRAVITY = Gravity.START | Gravity.CENTER_VERTICAL;
@@ -100,6 +101,7 @@ public class ActionBarView extends AbsActionBarView {
private TextView mTitleView;
private TextView mSubtitleView;
private View mTitleUpView;
+ private ViewGroup mUpGoerFive;
private Spinner mSpinner;
private LinearLayout mListNavLayout;
@@ -120,6 +122,7 @@ public class ActionBarView extends AbsActionBarView {
private boolean mIncludeTabs;
private boolean mIsCollapsable;
private boolean mIsCollapsed;
+ private boolean mWasHomeEnabled; // Was it enabled before action view expansion?
private MenuBuilder mOptionsMenu;
@@ -137,10 +140,6 @@ public class ActionBarView extends AbsActionBarView {
Window.Callback mWindowCallback;
- private final Rect mTempRect = new Rect();
- private int mMaxHomeSlop;
- private static final int MAX_HOME_SLOP = 32; // dp
-
private final AdapterView.OnItemSelectedListener mNavItemSelectedListener =
new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView parent, View view, int position, long id) {
@@ -219,14 +218,25 @@ public class ActionBarView extends AbsActionBarView {
com.android.internal.R.styleable.ActionBar_homeLayout,
com.android.internal.R.layout.action_bar_home);
- mHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
+ mUpGoerFive = (ViewGroup) inflater.inflate(
+ com.android.internal.R.layout.action_bar_up_container, this, false);
+ mHomeLayout = (HomeView) inflater.inflate(homeResId, mUpGoerFive, false);
- mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
+ mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, mUpGoerFive, false);
mExpandedHomeLayout.setUp(true);
mExpandedHomeLayout.setOnClickListener(mExpandedActionViewUpListener);
mExpandedHomeLayout.setContentDescription(getResources().getText(
R.string.action_bar_up_description));
+ // This needs to highlight/be focusable on its own.
+ // TODO: Clean up the handoff between expanded/normal.
+ final Drawable upBackground = mUpGoerFive.getBackground();
+ if (upBackground != null) {
+ mExpandedHomeLayout.setBackground(upBackground.getConstantState().newDrawable());
+ }
+ mExpandedHomeLayout.setEnabled(true);
+ mExpandedHomeLayout.setFocusable(true);
+
mTitleStyleRes = a.getResourceId(R.styleable.ActionBar_titleTextStyle, 0);
mSubtitleStyleRes = a.getResourceId(R.styleable.ActionBar_subtitleTextStyle, 0);
mProgressStyle = a.getResourceId(R.styleable.ActionBar_progressBarStyle, 0);
@@ -250,16 +260,14 @@ public class ActionBarView extends AbsActionBarView {
a.recycle();
mLogoNavItem = new ActionMenuItem(context, 0, android.R.id.home, 0, 0, mTitle);
- mHomeLayout.setOnClickListener(mUpClickListener);
- mHomeLayout.setClickable(true);
- mHomeLayout.setFocusable(true);
+
+ mUpGoerFive.setOnClickListener(mUpClickListener);
+ mUpGoerFive.setClickable(true);
+ mUpGoerFive.setFocusable(true);
if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
}
-
- mMaxHomeSlop =
- (int) (MAX_HOME_SLOP * context.getResources().getDisplayMetrics().density + 0.5f);
}
@Override
@@ -269,8 +277,8 @@ public class ActionBarView extends AbsActionBarView {
mTitleView = null;
mSubtitleView = null;
mTitleUpView = null;
- if (mTitleLayout != null && mTitleLayout.getParent() == this) {
- removeView(mTitleLayout);
+ if (mTitleLayout != null && mTitleLayout.getParent() == mUpGoerFive) {
+ mUpGoerFive.removeView(mTitleLayout);
}
mTitleLayout = null;
if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
@@ -551,19 +559,34 @@ public class ActionBarView extends AbsActionBarView {
}
public void setHomeButtonEnabled(boolean enable) {
- mHomeLayout.setEnabled(enable);
- mHomeLayout.setFocusable(enable);
+ setHomeButtonEnabled(enable, true);
+ }
+
+ private void setHomeButtonEnabled(boolean enable, boolean recordState) {
+ if (recordState) {
+ mWasHomeEnabled = enable;
+ }
+
+ if (mExpandedActionView != null) {
+ // There's an action view currently showing and we want to keep the state
+ // configured for the action view at the moment. If we needed to record the
+ // new state for later we will have done so above.
+ return;
+ }
+
+ mUpGoerFive.setEnabled(enable);
+ mUpGoerFive.setFocusable(enable);
// Make sure the home button has an accurate content description for accessibility.
if (!enable) {
- mHomeLayout.setContentDescription(null);
- mHomeLayout.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+ mUpGoerFive.setContentDescription(null);
+ mUpGoerFive.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
} else {
- mHomeLayout.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+ mUpGoerFive.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_AUTO);
if ((mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
- mHomeLayout.setContentDescription(mContext.getResources().getText(
+ mUpGoerFive.setContentDescription(mContext.getResources().getText(
R.string.action_bar_up_description));
} else {
- mHomeLayout.setContentDescription(mContext.getResources().getText(
+ mUpGoerFive.setContentDescription(mContext.getResources().getText(
R.string.action_bar_home_description));
}
}
@@ -600,7 +623,7 @@ public class ActionBarView extends AbsActionBarView {
if ((options & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
initTitle();
} else {
- removeView(mTitleLayout);
+ mUpGoerFive.removeView(mTitleLayout);
}
}
@@ -608,8 +631,6 @@ public class ActionBarView extends AbsActionBarView {
(ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME)) != 0) {
final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0;
mTitleUpView.setVisibility(!showHome ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE);
- mTitleLayout.setEnabled(!showHome && homeAsUp);
- mTitleLayout.setClickable(!showHome && homeAsUp);
}
if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
@@ -620,6 +641,17 @@ public class ActionBarView extends AbsActionBarView {
}
}
+ if (mTitleLayout != null &&
+ (flagsChanged & ActionBar.DISPLAY_TITLE_MULTIPLE_LINES) != 0) {
+ if ((options & ActionBar.DISPLAY_TITLE_MULTIPLE_LINES) != 0) {
+ mTitleView.setSingleLine(false);
+ mTitleView.setMaxLines(2);
+ } else {
+ mTitleView.setMaxLines(1);
+ mTitleView.setSingleLine(true);
+ }
+ }
+
requestLayout();
} else {
invalidate();
@@ -753,7 +785,8 @@ public class ActionBarView extends AbsActionBarView {
protected void onFinishInflate() {
super.onFinishInflate();
- addView(mHomeLayout);
+ mUpGoerFive.addView(mHomeLayout, 0);
+ addView(mUpGoerFive);
if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
final ViewParent parent = mCustomNavView.getParent();
@@ -775,8 +808,6 @@ public class ActionBarView extends AbsActionBarView {
mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
mTitleUpView = (View) mTitleLayout.findViewById(R.id.up);
- mTitleLayout.setOnClickListener(mUpClickListener);
-
if (mTitleStyleRes != 0) {
mTitleView.setTextAppearance(mContext, mTitleStyleRes);
}
@@ -796,11 +827,9 @@ public class ActionBarView extends AbsActionBarView {
final boolean showHome = (mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0;
final boolean showTitleUp = !showHome;
mTitleUpView.setVisibility(showTitleUp ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE);
- mTitleLayout.setEnabled(homeAsUp && showTitleUp);
- mTitleLayout.setClickable(homeAsUp && showTitleUp);
}
- addView(mTitleLayout);
+ mUpGoerFive.addView(mTitleLayout);
if (mExpandedActionView != null ||
(TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle))) {
// Don't show while in expanded mode or with empty text
@@ -820,6 +849,28 @@ public class ActionBarView extends AbsActionBarView {
return mIsCollapsed;
}
+ /**
+ * @return True if any characters in the title were truncated
+ */
+ public boolean isTitleTruncated() {
+ if (mTitleView == null) {
+ return false;
+ }
+
+ final Layout titleLayout = mTitleView.getLayout();
+ if (titleLayout == null) {
+ return false;
+ }
+
+ final int lineCount = titleLayout.getLineCount();
+ for (int i = 0; i < lineCount; i++) {
+ if (titleLayout.getEllipsisCount(i) > 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int childCount = getChildCount();
@@ -828,7 +879,16 @@ public class ActionBarView extends AbsActionBarView {
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE &&
- !(child == mMenuView && mMenuView.getChildCount() == 0)) {
+ !(child == mMenuView && mMenuView.getChildCount() == 0) &&
+ child != mUpGoerFive) {
+ visibleChildren++;
+ }
+ }
+
+ final int upChildCount = mUpGoerFive.getChildCount();
+ for (int i = 0; i < upChildCount; i++) {
+ final View child = mUpGoerFive.getChildAt(i);
+ if (child.getVisibility() != GONE) {
visibleChildren++;
}
}
@@ -872,7 +932,8 @@ public class ActionBarView extends AbsActionBarView {
HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
- if (homeLayout.getVisibility() != GONE) {
+ int homeWidth = 0;
+ if (homeLayout.getVisibility() != GONE && homeLayout.getParent() == mUpGoerFive) {
final ViewGroup.LayoutParams lp = homeLayout.getLayoutParams();
int homeWidthSpec;
if (lp.width < 0) {
@@ -880,10 +941,18 @@ public class ActionBarView extends AbsActionBarView {
} else {
homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
}
+
+ /*
+ * This is a little weird.
+ * We're only measuring the *home* affordance within the Up container here
+ * on purpose, because we want to give the available space to all other views before
+ * the title text. We'll remeasure the whole up container again later.
+ */
homeLayout.measure(homeWidthSpec, exactHeightSpec);
- final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getStartOffset();
- availableWidth = Math.max(0, availableWidth - homeWidth);
- leftOfCenter = Math.max(0, availableWidth - homeWidth);
+ homeWidth = homeLayout.getMeasuredWidth();
+ final int homeOffsetWidth = homeWidth + homeLayout.getStartOffset();
+ availableWidth = Math.max(0, availableWidth - homeOffsetWidth);
+ leftOfCenter = Math.max(0, availableWidth - homeOffsetWidth);
}
if (mMenuView != null && mMenuView.getParent() == this) {
@@ -985,9 +1054,13 @@ public class ActionBarView extends AbsActionBarView {
availableWidth -= horizontalMargin + customView.getMeasuredWidth();
}
- if (mExpandedActionView == null && showTitle) {
- availableWidth = measureChildView(mTitleLayout, availableWidth,
- MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
+ /*
+ * Measure the whole up container now, allowing for the full home+title sections.
+ * (This will re-measure the home view.)
+ */
+ availableWidth = measureChildView(mUpGoerFive, availableWidth + homeWidth,
+ MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0);
+ if (mTitleLayout != null) {
leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
}
@@ -1034,24 +1107,17 @@ public class ActionBarView extends AbsActionBarView {
final int y = getPaddingTop();
HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
- boolean needsTouchDelegate = false;
- int homeSlop = mMaxHomeSlop;
- int homeRight = 0;
- if (homeLayout.getVisibility() != GONE) {
- final int startOffset = homeLayout.getStartOffset();
- x += positionChild(homeLayout,
- next(x, startOffset, isLayoutRtl), y, contentHeight, isLayoutRtl);
- x = next(x, startOffset, isLayoutRtl);
- needsTouchDelegate = homeLayout == mHomeLayout;
- homeRight = x;
- }
+ final int startOffset = homeLayout.getVisibility() != GONE &&
+ homeLayout.getParent() == mUpGoerFive ? homeLayout.getStartOffset() : 0;
+
+ // Position the up container based on where the edge of the home layout should go.
+ x += positionChild(mUpGoerFive,
+ next(x, startOffset, isLayoutRtl), y, contentHeight, isLayoutRtl);
+ x = next(x, startOffset, isLayoutRtl);
if (mExpandedActionView == null) {
final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
(mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
- if (showTitle) {
- x += positionChild(mTitleLayout, x, y, contentHeight, isLayoutRtl);
- }
switch (mNavigationMode) {
case ActionBar.NAVIGATION_MODE_STANDARD:
@@ -1061,7 +1127,6 @@ public class ActionBarView extends AbsActionBarView {
if (showTitle) {
x = next(x, mItemPadding, isLayoutRtl);
}
- homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0));
x += positionChild(mListNavLayout, x, y, contentHeight, isLayoutRtl);
x = next(x, mItemPadding, isLayoutRtl);
}
@@ -1069,7 +1134,6 @@ public class ActionBarView extends AbsActionBarView {
case ActionBar.NAVIGATION_MODE_TABS:
if (mTabScrollView != null) {
if (showTitle) x = next(x, mItemPadding, isLayoutRtl);
- homeSlop = Math.min(homeSlop, Math.max(x - homeRight, 0));
x += positionChild(mTabScrollView, x, y, contentHeight, isLayoutRtl);
x = next(x, mItemPadding, isLayoutRtl);
}
@@ -1174,7 +1238,6 @@ public class ActionBarView extends AbsActionBarView {
final int customWidth = customView.getMeasuredWidth();
customView.layout(xpos, ypos, xpos + customWidth,
ypos + customView.getMeasuredHeight());
- homeSlop = Math.min(homeSlop, Math.max(xpos - homeRight, 0));
x = next(x, customWidth, isLayoutRtl);
}
@@ -1184,14 +1247,6 @@ public class ActionBarView extends AbsActionBarView {
mProgressView.layout(mProgressBarPadding, -halfProgressHeight,
mProgressBarPadding + mProgressView.getMeasuredWidth(), halfProgressHeight);
}
-
- if (needsTouchDelegate) {
- mTempRect.set(homeLayout.getLeft(), homeLayout.getTop(),
- homeLayout.getRight() + homeSlop, homeLayout.getBottom());
- setTouchDelegate(new TouchDelegate(mTempRect, homeLayout));
- } else {
- setTouchDelegate(null);
- }
}
@Override
@@ -1491,14 +1546,15 @@ public class ActionBarView extends AbsActionBarView {
if (mExpandedActionView.getParent() != ActionBarView.this) {
addView(mExpandedActionView);
}
- if (mExpandedHomeLayout.getParent() != ActionBarView.this) {
- addView(mExpandedHomeLayout);
+ if (mExpandedHomeLayout.getParent() != mUpGoerFive) {
+ mUpGoerFive.addView(mExpandedHomeLayout);
}
mHomeLayout.setVisibility(GONE);
if (mTitleLayout != null) mTitleLayout.setVisibility(GONE);
if (mTabScrollView != null) mTabScrollView.setVisibility(GONE);
if (mSpinner != null) mSpinner.setVisibility(GONE);
if (mCustomNavView != null) mCustomNavView.setVisibility(GONE);
+ setHomeButtonEnabled(false, false);
requestLayout();
item.setActionViewExpanded(true);
@@ -1518,7 +1574,7 @@ public class ActionBarView extends AbsActionBarView {
}
removeView(mExpandedActionView);
- removeView(mExpandedHomeLayout);
+ mUpGoerFive.removeView(mExpandedHomeLayout);
mExpandedActionView = null;
if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) {
mHomeLayout.setVisibility(VISIBLE);
@@ -1541,6 +1597,7 @@ public class ActionBarView extends AbsActionBarView {
}
mExpandedHomeLayout.setIcon(null);
mCurrentExpandedItem = null;
+ setHomeButtonEnabled(mWasHomeEnabled); // Set by expandItemActionView above
requestLayout();
item.setActionViewExpanded(false);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 75fef24..907b52a 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -24,7 +24,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Binder;
-import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -54,8 +53,6 @@ import java.util.List;
*/
public class LockPatternUtils {
- private static final String OPTION_ENABLE_FACELOCK = "enable_facelock";
-
private static final String TAG = "LockPatternUtils";
/**
@@ -116,16 +113,6 @@ public class LockPatternUtils {
public static final String KEYGUARD_SHOW_APPWIDGET = "showappwidget";
/**
- * Options used to lock the device upon user switch.
- */
- public static final Bundle USER_SWITCH_LOCK_OPTIONS = new Bundle();
-
- static {
- USER_SWITCH_LOCK_OPTIONS.putBoolean(KEYGUARD_SHOW_USER_SWITCHER, true);
- USER_SWITCH_LOCK_OPTIONS.putBoolean(KEYGUARD_SHOW_SECURITY_CHALLENGE, true);
- }
-
- /**
* The bit in LOCK_BIOMETRIC_WEAK_FLAGS to be used to indicate whether liveliness should
* be used
*/