diff options
Diffstat (limited to 'core/java/android')
35 files changed, 631 insertions, 232 deletions
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/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..8f8df0a 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -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/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/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java index cb61a71..24fd2e4 100644 --- a/core/java/android/appwidget/AppWidgetHost.java +++ b/core/java/android/appwidget/AppWidgetHost.java @@ -224,6 +224,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) { diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index 3dd640c..77315f9 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -544,8 +544,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 = diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java index 26bde19..d7a214d 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; } @@ -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/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/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/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/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/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/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/View.java b/core/java/android/view/View.java index ff44475..1747627 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -623,6 +623,7 @@ import java.util.concurrent.atomic.AtomicInteger; * @attr ref android.R.styleable#View_hapticFeedbackEnabled * @attr ref android.R.styleable#View_keepScreenOn * @attr ref android.R.styleable#View_layerType + * @attr ref android.R.styleable#View_layoutDirection * @attr ref android.R.styleable#View_longClickable * @attr ref android.R.styleable#View_minHeight * @attr ref android.R.styleable#View_minWidth @@ -660,6 +661,7 @@ import java.util.concurrent.atomic.AtomicInteger; * @attr ref android.R.styleable#View_soundEffectsEnabled * @attr ref android.R.styleable#View_tag * @attr ref android.R.styleable#View_textAlignment + * @attr ref android.R.styleable#View_textDirection * @attr ref android.R.styleable#View_transformPivotX * @attr ref android.R.styleable#View_transformPivotY * @attr ref android.R.styleable#View_translationX @@ -5854,6 +5856,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * {@link #LAYOUT_DIRECTION_RTL}, * {@link #LAYOUT_DIRECTION_INHERIT} or * {@link #LAYOUT_DIRECTION_LOCALE}. + * * @attr ref android.R.styleable#View_layoutDirection * * @hide @@ -5909,6 +5912,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}. + * + * @attr ref android.R.styleable#View_layoutDirection */ @ViewDebug.ExportedProperty(category = "layout", mapping = { @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"), @@ -16627,6 +16632,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * {@link #TEXT_DIRECTION_RTL}, * {@link #TEXT_DIRECTION_LOCALE} * + * @attr ref android.R.styleable#View_textDirection + * * @hide */ @ViewDebug.ExportedProperty(category = "text", mapping = { @@ -16656,6 +16663,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution * proceeds up the parent chain of the view to get the value. If there is no parent, then it will * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}. + * + * @attr ref android.R.styleable#View_textDirection */ public void setTextDirection(int textDirection) { if (getRawTextDirection() != textDirection) { @@ -16684,6 +16693,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * {@link #TEXT_DIRECTION_LTR}, * {@link #TEXT_DIRECTION_RTL}, * {@link #TEXT_DIRECTION_LOCALE} + * + * @attr ref android.R.styleable#View_textDirection */ public int getTextDirection() { return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT; @@ -16816,6 +16827,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * {@link #TEXT_ALIGNMENT_VIEW_START}, * {@link #TEXT_ALIGNMENT_VIEW_END} * + * @attr ref android.R.styleable#View_textAlignment + * * @hide */ @ViewDebug.ExportedProperty(category = "text", mapping = { @@ -16879,6 +16892,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * {@link #TEXT_ALIGNMENT_TEXT_END}, * {@link #TEXT_ALIGNMENT_VIEW_START}, * {@link #TEXT_ALIGNMENT_VIEW_END} + * + * @attr ref android.R.styleable#View_textAlignment */ @ViewDebug.ExportedProperty(category = "text", mapping = { @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"), 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..85972c3 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -291,6 +291,7 @@ public class Editor { mErrorWasChanged = true; if (mError == null) { + setErrorIcon(null); if (mErrorPopup != null) { if (mErrorPopup.isShowing()) { mErrorPopup.dismiss(); @@ -299,21 +300,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 +325,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 +342,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 +375,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() { @@ -3726,7 +3754,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); diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index e52e84d..49523a2 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,32 @@ 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)) { + myWidth = 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); + + myWidth += child.getMeasuredWidth(); + myWidth += params.leftMargin + params.rightMargin; + } + } + } + for (int i = 0; i < count; i++) { View child = views[i]; if (child.getVisibility() != GONE) { @@ -924,7 +950,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 +1001,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/TextView.java b/core/java/android/widget/TextView.java index 5d90400..22bfadb 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -284,15 +284,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; @@ -4734,6 +4863,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 +4887,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 +4906,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 +4917,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 +5003,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 +8368,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 +8402,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 +8413,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * @hide */ protected void resetResolvedDrawables() { + super.resetResolvedDrawables(); mLastLayoutDirection = -1; } 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() { |
