diff options
Diffstat (limited to 'core/java/android')
23 files changed, 380 insertions, 469 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index ffcdcf7..2e66a4c 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -54,7 +54,6 @@ import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.media.session.MediaController; -import android.media.session.MediaSession; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -5641,8 +5640,8 @@ public class Activity extends ContextThemeWrapper if (info.taskAffinity == null) { return false; } - return !ActivityManagerNative.getDefault() - .targetTaskAffinityMatchesActivity(mToken, info.taskAffinity); + return ActivityManagerNative.getDefault() + .shouldUpRecreateTask(mToken, info.taskAffinity); } catch (RemoteException e) { return false; } catch (NameNotFoundException e) { diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 3dafa4b..5b81cc3 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1997,11 +1997,11 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } - case TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION: { + case SHOULD_UP_RECREATE_TASK_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); String destAffinity = data.readString(); - boolean res = targetTaskAffinityMatchesActivity(token, destAffinity); + boolean res = shouldUpRecreateTask(token, destAffinity); reply.writeNoException(); reply.writeInt(res ? 1 : 0); return true; @@ -4858,14 +4858,14 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } - public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity) + public boolean shouldUpRecreateTask(IBinder token, String destAffinity) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(token); data.writeString(destAffinity); - mRemote.transact(TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION, data, reply, 0); + mRemote.transact(SHOULD_UP_RECREATE_TASK_TRANSACTION, data, reply, 0); reply.readException(); boolean result = reply.readInt() != 0; data.recycle(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 70514d8..1664408 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -393,7 +393,7 @@ public interface IActivityManager extends IInterface { public void keyguardWaitingForActivityDrawn() throws RemoteException; - public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity) + public boolean shouldUpRecreateTask(IBinder token, String destAffinity) throws RemoteException; public boolean navigateUpTo(IBinder token, Intent target, int resultCode, Intent resultData) @@ -702,7 +702,7 @@ public interface IActivityManager extends IInterface { int GET_MY_MEMORY_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+142; int KILL_PROCESSES_BELOW_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+143; int GET_CURRENT_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+144; - int TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+145; + int SHOULD_UP_RECREATE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+145; int NAVIGATE_UP_TO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+146; int SET_LOCK_SCREEN_SHOWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+147; int FINISH_ACTIVITY_AFFINITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+148; diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 47967ba..f7300aa 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -2579,20 +2579,35 @@ public class Notification implements Parcelable return bitmap; } + private boolean addProfileBadge(RemoteViews contentView, int resId) { + Bitmap profileBadge = getProfileBadge(); + + contentView.setViewVisibility(R.id.profile_badge_large_template, View.GONE); + contentView.setViewVisibility(R.id.profile_badge_line2, View.GONE); + contentView.setViewVisibility(R.id.profile_badge_line3, View.GONE); + + if (profileBadge != null) { + contentView.setImageViewBitmap(resId, profileBadge); + contentView.setViewVisibility(resId, View.VISIBLE); + + // Make sure Line 3 is visible. As badge will be here if there + // is no text to display. + if (resId == R.id.profile_badge_line3) { + contentView.setViewVisibility(R.id.line3, View.VISIBLE); + } + return true; + } + return false; + } + private RemoteViews applyStandardTemplate(int resId) { - Bitmap profileIcon = getProfileBadge(); RemoteViews contentView = new BuilderRemoteViews(mContext.getPackageName(), mOriginatingUserId, resId); boolean showLine3 = false; boolean showLine2 = false; + boolean contentTextInLine2 = false; - if (profileIcon != null) { - contentView.setImageViewBitmap(R.id.profile_icon, profileIcon); - contentView.setViewVisibility(R.id.profile_icon, View.VISIBLE); - } else { - contentView.setViewVisibility(R.id.profile_icon, View.GONE); - } if (mLargeIcon != null) { contentView.setImageViewBitmap(R.id.icon, mLargeIcon); processLargeIcon(mLargeIcon, contentView); @@ -2639,6 +2654,7 @@ public class Notification implements Parcelable contentView.setTextViewText(R.id.text2, processLegacyText(mContentText)); contentView.setViewVisibility(R.id.text2, View.VISIBLE); showLine2 = true; + contentTextInLine2 = true; } else { contentView.setViewVisibility(R.id.text2, View.GONE); } @@ -2681,6 +2697,15 @@ public class Notification implements Parcelable hasThreeLines(), mContext.getResources().getConfiguration().fontScale), 0, 0); + // We want to add badge to first line of text. + boolean addedBadge = addProfileBadge(contentView, + contentTextInLine2 ? R.id.profile_badge_line2 : R.id.profile_badge_line3); + // If we added the badge to line 3 then we should show line 3. + if (addedBadge && !contentTextInLine2) { + showLine3 = true; + } + + // Note getStandardView may hide line 3 again. contentView.setViewVisibility(R.id.line3, showLine3 ? View.VISIBLE : View.GONE); contentView.setViewVisibility(R.id.overflow_divider, showLine3 ? View.VISIBLE : View.GONE); return contentView; @@ -3347,6 +3372,8 @@ public class Notification implements Parcelable contentView.setViewVisibility(R.id.overflow_divider, View.VISIBLE); contentView.setViewVisibility(R.id.line3, View.VISIBLE); } else { + // Clear text in case we use the line to show the profile badge. + contentView.setTextViewText(R.id.text, ""); contentView.setViewVisibility(R.id.overflow_divider, View.GONE); contentView.setViewVisibility(R.id.line3, View.GONE); } @@ -3507,6 +3534,9 @@ public class Notification implements Parcelable applyTopPadding(contentView); + boolean twoTextLines = mBuilder.mSubText != null && mBuilder.mContentText != null; + mBuilder.addProfileBadge(contentView, + twoTextLines ? R.id.profile_badge_line2 : R.id.profile_badge_line3); return contentView; } @@ -3632,6 +3662,8 @@ public class Notification implements Parcelable applyTopPadding(contentView); + mBuilder.addProfileBadge(contentView, R.id.profile_badge_large_template); + return contentView; } @@ -3769,6 +3801,8 @@ public class Notification implements Parcelable applyTopPadding(contentView); + mBuilder.addProfileBadge(contentView, R.id.profile_badge_large_template); + return contentView; } diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java index b7af544..e4ed470e 100644 --- a/core/java/android/app/job/JobInfo.java +++ b/core/java/android/app/job/JobInfo.java @@ -26,6 +26,9 @@ import android.os.PersistableBundle; * Container of data passed to the {@link android.app.job.JobScheduler} fully encapsulating the * parameters required to schedule work against the calling application. These are constructed * using the {@link JobInfo.Builder}. + * You must specify at least one sort of constraint on the JobInfo object that you are creating. + * The goal here is to provide the scheduler with high-level semantics about the work you want to + * accomplish. Doing otherwise with throw an exception in your app. */ public class JobInfo implements Parcelable { public interface NetworkType { @@ -434,7 +437,7 @@ public class JobInfo implements Parcelable { * @return The job object to hand to the JobScheduler. This object is immutable. */ public JobInfo build() { - // Allow tasks with no constraints. What am I, a database? + // Allow jobs with no constraints - What am I, a database? if (!mHasEarlyConstraint && !mHasLateConstraint && !mRequiresCharging && !mRequiresDeviceIdle && mNetworkCapabilities == NetworkType.NONE) { throw new IllegalArgumentException("You're trying to build a job with no " + diff --git a/core/java/android/hardware/hdmi/HdmiClient.java b/core/java/android/hardware/hdmi/HdmiClient.java index f95ed0f..aba90e4 100644 --- a/core/java/android/hardware/hdmi/HdmiClient.java +++ b/core/java/android/hardware/hdmi/HdmiClient.java @@ -50,7 +50,7 @@ public abstract class HdmiClient { try { mService.sendKeyEvent(getDeviceType(), keyCode, isPressed); } catch (RemoteException e) { - Log.e(TAG, "queryDisplayStatus threw exception ", e); + Log.e(TAG, "sendKeyEvent threw exception ", e); } } diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java index 354c05e..c37fb5b 100644 --- a/core/java/android/hardware/hdmi/HdmiTvClient.java +++ b/core/java/android/hardware/hdmi/HdmiTvClient.java @@ -35,6 +35,11 @@ import libcore.util.EmptyArray; public final class HdmiTvClient extends HdmiClient { private static final String TAG = "HdmiTvClient"; + /** + * Size of MHL scratchpad register. + */ + public static final int SCRATCHPAD_DATA_SIZE = 16; + HdmiTvClient(IHdmiControlService service) { super(service); } @@ -80,6 +85,15 @@ public final class HdmiTvClient extends HdmiClient { } } + private static IHdmiControlCallback getCallbackWrapper(final SelectCallback callback) { + return new IHdmiControlCallback.Stub() { + @Override + public void onComplete(int result) { + callback.onComplete(result); + } + }; + } + /** * Select a HDMI port to be a new route path. * @@ -126,6 +140,15 @@ public final class HdmiTvClient extends HdmiClient { } } + private static IHdmiInputChangeListener getListenerWrapper(final InputChangeListener listener) { + return new IHdmiInputChangeListener.Stub() { + @Override + public void onChanged(HdmiDeviceInfo info) { + listener.onChanged(info); + } + }; + } + /** * Set system audio volume * @@ -170,6 +193,38 @@ public final class HdmiTvClient extends HdmiClient { } } + private static IHdmiRecordListener getListenerWrapper(final HdmiRecordListener callback) { + return new IHdmiRecordListener.Stub() { + @Override + public byte[] getOneTouchRecordSource(int recorderAddress) { + HdmiRecordSources.RecordSource source = + callback.getOneTouchRecordSource(recorderAddress); + if (source == null) { + return EmptyArray.BYTE; + } + byte[] data = new byte[source.getDataSize(true)]; + source.toByteArray(true, data, 0); + return data; + } + + @Override + public void onOneTouchRecordResult(int result) { + callback.onOneTouchRecordResult(result); + } + + @Override + public void onTimerRecordingResult(int result) { + callback.onTimerRecordingResult( + HdmiRecordListener.TimerStatusData.parseFrom(result)); + } + + @Override + public void onClearTimerRecordingResult(int result) { + callback.onClearTimerRecordingResult(result); + } + }; + } + /** * Start one touch recording with the given recorder address and recorder source. * <p> @@ -276,53 +331,63 @@ public final class HdmiTvClient extends HdmiClient { } } - private static IHdmiControlCallback getCallbackWrapper(final SelectCallback callback) { - return new IHdmiControlCallback.Stub() { - @Override - public void onComplete(int result) { - callback.onComplete(result); - } - }; + /** + * Interface used to get incoming MHL scratchpad command. + */ + public interface HdmiMhlScratchpadCommandListener { + void onReceived(int portId, int offset, int length, byte[] data); } - private static IHdmiInputChangeListener getListenerWrapper(final InputChangeListener listener) { - return new IHdmiInputChangeListener.Stub() { - @Override - public void onChanged(HdmiDeviceInfo info) { - listener.onChanged(info); - } - }; + /** + * Set {@link HdmiMhlScratchpadCommandListener} to get incoming MHL sSratchpad command. + * + * @param listener to receive incoming MHL Scratchpad command + */ + public void setHdmiMhlScratchpadCommandListener(HdmiMhlScratchpadCommandListener listener) { + if (listener == null) { + throw new IllegalArgumentException("listener must not be null."); + } + try { + mService.addHdmiMhlScratchpadCommandListener(getListenerWrapper(listener)); + } catch (RemoteException e) { + Log.e(TAG, "failed to set hdmi mhl scratchpad command listener: ", e); + } } - private static IHdmiRecordListener getListenerWrapper(final HdmiRecordListener callback) { - return new IHdmiRecordListener.Stub() { + private IHdmiMhlScratchpadCommandListener getListenerWrapper( + final HdmiMhlScratchpadCommandListener listener) { + return new IHdmiMhlScratchpadCommandListener.Stub() { @Override - public byte[] getOneTouchRecordSource(int recorderAddress) { - HdmiRecordSources.RecordSource source = - callback.getOneTouchRecordSource(recorderAddress); - if (source == null) { - return EmptyArray.BYTE; - } - byte[] data = new byte[source.getDataSize(true)]; - source.toByteArray(true, data, 0); - return data; - } - - @Override - public void onOneTouchRecordResult(int result) { - callback.onOneTouchRecordResult(result); + public void onReceived(int portId, int offset, int length, byte[] data) { + listener.onReceived(portId, offset, length, data); } + }; + } - @Override - public void onTimerRecordingResult(int result) { - callback.onTimerRecordingResult( - HdmiRecordListener.TimerStatusData.parseFrom(result)); - } + /** + * Send MHL Scratchpad command to the device connected to a port of the given portId. + * + * @param portId id of port to send MHL Scratchpad command + * @param offset offset in the in given data + * @param length length of data. offset + length should be bound to length of data. + * @param data container for Scratchpad data. It should be 16 bytes. + * @throws IllegalArgumentException if the given parameters are invalid + */ + public void sendScratchpadCommand(int portId, int offset, int length, byte[] data) { + if (data == null || data.length != SCRATCHPAD_DATA_SIZE) { + throw new IllegalArgumentException("Invalid scratchpad data."); + } + if (offset < 0 || offset >= SCRATCHPAD_DATA_SIZE) { + throw new IllegalArgumentException("Invalid offset:" + offset); + } + if (length < 0 || offset + length > SCRATCHPAD_DATA_SIZE) { + throw new IllegalArgumentException("Invalid length:" + length); + } - @Override - public void onClearTimerRecordingResult(int result) { - callback.onClearTimerRecordingResult(result); - } - }; + try { + mService.sendScratchpadCommand(portId, offset, length, data); + } catch (RemoteException e) { + Log.e(TAG, "failed to send scratchpad command: ", e); + } } } diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl index 17f290b..3bd45ed 100644 --- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl +++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl @@ -22,6 +22,7 @@ import android.hardware.hdmi.IHdmiControlCallback; import android.hardware.hdmi.IHdmiDeviceEventListener; import android.hardware.hdmi.IHdmiHotplugEventListener; import android.hardware.hdmi.IHdmiInputChangeListener; +import android.hardware.hdmi.IHdmiMhlScratchpadCommandListener; import android.hardware.hdmi.IHdmiRecordListener; import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener; import android.hardware.hdmi.IHdmiVendorCommandListener; @@ -66,4 +67,6 @@ interface IHdmiControlService { void stopOneTouchRecord(int recorderAddress); void startTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource); void clearTimerRecording(int recorderAddress, int sourceType, in byte[] recordSource); + void sendScratchpadCommand(int portId, int offset, int length, in byte[] data); + void addHdmiMhlScratchpadCommandListener(IHdmiMhlScratchpadCommandListener listener); } diff --git a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl b/core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl index 41ef7cc6..4176597 100644 --- a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl +++ b/core/java/android/hardware/hdmi/IHdmiMhlScratchpadCommandListener.aidl @@ -14,6 +14,14 @@ * limitations under the License. */ -package android.view.inputmethod; +package android.hardware.hdmi; -parcelable CursorAnchorInfoRequest; + /** + * Callback interface definition for MHL client to get the scratchpad + * command. + * + * @hide + */ + oneway interface IHdmiMhlScratchpadCommandListener { + void onReceived(int portId, int offset, int length, in byte[] data); + } diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index ba811b7..2eb42a7 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -53,7 +53,6 @@ import android.view.WindowManager.BadTokenException; import android.view.animation.AnimationUtils; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CursorAnchorInfo; -import android.view.inputmethod.CursorAnchorInfoRequest; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; @@ -1711,13 +1710,12 @@ public class InputMethodService extends AbstractInputMethodService { } /** - * Called when the application has reported a new location of its text cursor. This is only - * called if explicitly requested by the input method. The default implementation does nothing. - * @param newCursor The new cursor position, in screen coordinates if the input method calls - * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} with - * {@link CursorAnchorInfoRequest#FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES}. Otherwise, - * this is in local coordinates. + * Called when the application has reported a new location of its text + * cursor. This is only called if explicitly requested by the input method. + * The default implementation does nothing. + * @deprecated Use {#link onUpdateCursorAnchorInfo(CursorAnchorInfo)} instead. */ + @Deprecated public void onUpdateCursor(Rect newCursor) { // Intentionally empty } diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java index 0de3f26..d2a4728 100644 --- a/core/java/android/net/Network.java +++ b/core/java/android/net/Network.java @@ -16,10 +16,10 @@ package android.net; -import android.net.NetworkBoundURLFactory; import android.net.NetworkUtils; import android.os.Parcelable; import android.os.Parcel; +import android.system.ErrnoException; import java.io.IOException; import java.net.InetAddress; @@ -30,6 +30,7 @@ import java.net.SocketAddress; import java.net.SocketException; import java.net.UnknownHostException; import java.net.URL; +import java.net.URLConnection; import java.net.URLStreamHandler; import java.util.concurrent.atomic.AtomicReference; import javax.net.SocketFactory; @@ -54,7 +55,7 @@ public class Network implements Parcelable { public final int netId; // Objects used to perform per-network operations such as getSocketFactory - // and getBoundURL, and a lock to protect access to them. + // and openConnection, and a lock to protect access to them. private volatile NetworkBoundSocketFactory mNetworkBoundSocketFactory = null; private volatile OkHttpClient mOkHttpClient = null; private Object mLock = new Object(); @@ -157,12 +158,7 @@ public class Network implements Parcelable { @Override public Socket createSocket() throws IOException { Socket socket = new Socket(); - // Query a property of the underlying socket to ensure the underlying - // socket exists so a file descriptor is available to bind to a network. - socket.getReuseAddress(); - if (!NetworkUtils.bindSocketToNetwork(socket.getFileDescriptor$().getInt$(), mNetId)) { - throw new SocketException("Failed to bind socket to network."); - } + bindSocket(socket); return socket; } } @@ -187,73 +183,63 @@ public class Network implements Parcelable { return mNetworkBoundSocketFactory; } - /** The default NetworkBoundURLFactory, used if setNetworkBoundURLFactory is never called. */ - private static final NetworkBoundURLFactory DEFAULT_URL_FACTORY = new NetworkBoundURLFactory() { - public URL getBoundURL(final Network network, URL url) throws MalformedURLException { - if (network.mOkHttpClient == null) { - synchronized (network.mLock) { - if (network.mOkHttpClient == null) { - HostResolver hostResolver = new HostResolver() { - @Override - public InetAddress[] getAllByName(String host) - throws UnknownHostException { - return network.getAllByName(host); - } - }; - network.mOkHttpClient = new OkHttpClient() - .setSocketFactory(network.getSocketFactory()) - .setHostResolver(hostResolver); - } + private void maybeInitHttpClient() { + if (mOkHttpClient == null) { + synchronized (mLock) { + if (mOkHttpClient == null) { + HostResolver hostResolver = new HostResolver() { + @Override + public InetAddress[] getAllByName(String host) throws UnknownHostException { + return Network.this.getAllByName(host); + } + }; + mOkHttpClient = new OkHttpClient() + .setSocketFactory(getSocketFactory()) + .setHostResolver(hostResolver); } } - - String protocol = url.getProtocol(); - URLStreamHandler handler = network.mOkHttpClient.createURLStreamHandler(protocol); - if (handler == null) { - // OkHttpClient only supports HTTP and HTTPS and returns a null URLStreamHandler if - // passed another protocol. - throw new MalformedURLException("Invalid URL or unrecognized protocol " + protocol); - } - return new URL(url, "", handler); } - }; - - private static AtomicReference<NetworkBoundURLFactory> sNetworkBoundURLFactory = - new AtomicReference <NetworkBoundURLFactory>(DEFAULT_URL_FACTORY); + } /** - * Returns a {@link URL} based on the given URL but bound to this {@code Network}, - * such that opening the URL will send all network traffic on this Network. + * Opens the specified {@link URL} on this {@code Network}, such that all traffic will be sent + * on this Network. The URL protocol must be {@code HTTP} or {@code HTTPS}. * - * Note that if this {@code Network} ever disconnects, any URL object generated by this method - * in the past or future will cease to work. - * - * The returned URL may have a {@link URLStreamHandler} explicitly set, which may not be the - * handler generated by the factory set with {@link java.net.URL#setURLStreamHandlerFactory}. To - * affect the {@code URLStreamHandler}s of URLs returned by this method, call - * {@link #setNetworkBoundURLFactory}. - * - * Because the returned URLs may have an explicit {@code URLStreamHandler} set, using them as a - * context when constructing other URLs and explicitly specifying a {@code URLStreamHandler} may - * result in URLs that are no longer bound to the same {@code Network}. - * - * The default implementation only supports {@code HTTP} and {@code HTTPS} URLs. - * - * @return a {@link URL} bound to this {@code Network}. + * @return a {@code URLConnection} to the resource referred to by this URL. + * @throws MalformedURLException if the URL protocol is not HTTP or HTTPS. + * @throws IOException if an error occurs while opening the connection. + * @see java.net.URL#openConnection() */ - public URL getBoundURL(URL url) throws MalformedURLException { - return sNetworkBoundURLFactory.get().getBoundURL(this, url); + public URLConnection openConnection(URL url) throws IOException { + maybeInitHttpClient(); + String protocol = url.getProtocol(); + URLStreamHandler handler = mOkHttpClient.createURLStreamHandler(protocol); + if (handler == null) { + // OkHttpClient only supports HTTP and HTTPS and returns a null URLStreamHandler if + // passed another protocol. + throw new MalformedURLException("Invalid URL or unrecognized protocol " + protocol); + } + return new URL(url, "", handler).openConnection(); } /** - * Sets the {@link NetworkBoundURLFactory} to be used by future {@link #getBoundURL} calls. - * If {@code null}, clears any factory that was previously specified. + * Binds the specified {@link Socket} to this {@code Network}. All data traffic on the socket + * will be sent on this {@code Network}, irrespective of any process-wide network binding set by + * {@link ConnectivityManager#setProcessDefaultNetwork}. The socket must not be connected. */ - public static void setNetworkBoundURLFactory(NetworkBoundURLFactory factory) { - if (factory == null) { - factory = DEFAULT_URL_FACTORY; + public void bindSocket(Socket socket) throws IOException { + if (socket.isConnected()) { + throw new SocketException("Socket is connected"); + } + // Query a property of the underlying socket to ensure the underlying + // socket exists so a file descriptor is available to bind to a network. + socket.getReuseAddress(); + int err = NetworkUtils.bindSocketToNetwork(socket.getFileDescriptor$().getInt$(), netId); + if (err != 0) { + // bindSocketToNetwork returns negative errno. + throw new ErrnoException("Binding socket to network " + netId, -err) + .rethrowAsSocketException(); } - sNetworkBoundURLFactory.set(factory); } // implement the Parcelable interface diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 54d8676..d2a2997 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -128,8 +128,9 @@ public class NetworkUtils { /** * Explicitly binds {@code socketfd} to the network designated by {@code netId}. This * overrides any binding via {@link #bindProcessToNetwork}. + * @return 0 on success or negative errno on failure. */ - public native static boolean bindSocketToNetwork(int socketfd, int netId); + public native static int bindSocketToNetwork(int socketfd, int netId); /** * Protect {@code socketfd} from VPN connections. After protecting, data sent through diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index 8db99a5..942da5a 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -24,13 +24,17 @@ import android.content.Context; import android.content.Intent; import android.content.pm.UserInfo; import android.database.Cursor; +import android.location.Country; +import android.location.CountryDetector; import android.net.Uri; import android.os.UserHandle; import android.os.UserManager; import android.provider.ContactsContract.CommonDataKinds.Callable; import android.provider.ContactsContract.CommonDataKinds.Phone; +import android.provider.ContactsContract.Data; import android.provider.ContactsContract.DataUsageFeedback; import android.telecomm.PhoneAccountHandle; +import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import com.android.internal.telephony.CallerInfo; @@ -345,6 +349,13 @@ public class CallLog { public static final String PHONE_ACCOUNT_ID = "subscription_id"; /** + * If a successful call is made that is longer than this duration, update the phone number + * in the ContactsProvider with the normalized version of the number, based on the user's + * current country code. + */ + private static final int MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS = 1000 * 10; + + /** * Adds a call to the call log. * * @param ci the CallerInfo object to get the target contact from. Can be null @@ -484,12 +495,13 @@ public class CallLog { if (cursor != null) { try { if (cursor.getCount() > 0 && cursor.moveToFirst()) { - final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() - .appendPath(cursor.getString(0)) - .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, - DataUsageFeedback.USAGE_TYPE_CALL) - .build(); - resolver.update(feedbackUri, new ContentValues(), null, null); + final String dataId = cursor.getString(0); + updateDataUsageStatForData(resolver, dataId); + if (duration >= MIN_DURATION_FOR_NORMALIZED_NUMBER_UPDATE_MS + && callType == Calls.OUTGOING_TYPE + && TextUtils.isEmpty(ci.normalizedNumber)) { + updateNormalizedNumber(context, resolver, dataId, number); + } } } finally { cursor.close(); @@ -562,5 +574,53 @@ public class CallLog { + " LIMIT -1 OFFSET 500)", null); return result; } + + private static void updateDataUsageStatForData(ContentResolver resolver, String dataId) { + final Uri feedbackUri = DataUsageFeedback.FEEDBACK_URI.buildUpon() + .appendPath(dataId) + .appendQueryParameter(DataUsageFeedback.USAGE_TYPE, + DataUsageFeedback.USAGE_TYPE_CALL) + .build(); + resolver.update(feedbackUri, new ContentValues(), null, null); + } + + /** + * Update the normalized phone number for the given dataId in the ContactsProvider, based + * on the user's current country. + */ + private static void updateNormalizedNumber(Context context, ContentResolver resolver, + String dataId, String number) { + if (TextUtils.isEmpty(number) || TextUtils.isEmpty(dataId)) { + return; + } + + final String countryIso = getCurrentCountryIso(context); + if (TextUtils.isEmpty(countryIso)) { + return; + } + + final String normalizedNumber = PhoneNumberUtils.formatNumberToE164(number, + getCurrentCountryIso(context)); + if (TextUtils.isEmpty(normalizedNumber)) { + return; + } + + final ContentValues values = new ContentValues(); + values.put(Phone.NORMALIZED_NUMBER, normalizedNumber); + resolver.update(Data.CONTENT_URI, values, Data._ID + "=?", new String[] {dataId}); + } + + private static String getCurrentCountryIso(Context context) { + String countryIso = null; + final CountryDetector detector = (CountryDetector) context.getSystemService( + Context.COUNTRY_DETECTOR); + if (detector != null) { + final Country country = detector.detectCountry(); + if (country != null) { + countryIso = country.getCountryIso(); + } + } + return countryIso; + } } } diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 681717c..964b054 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -657,11 +657,15 @@ public class KeyEvent extends InputEvent implements Parcelable { /** Key code constant: TV data service key. * Displays data services like weather, sports. */ public static final int KEYCODE_TV_DATA_SERVICE = 230; + /** Key code constant: Voice Assist key. + * Launches the global voice assist activity. Not delivered to applications. */ + public static final int KEYCODE_VOICE_ASSIST = 231; - private static final int LAST_KEYCODE = KEYCODE_TV_DATA_SERVICE; + private static final int LAST_KEYCODE = KEYCODE_VOICE_ASSIST; // NOTE: If you add a new keycode here you must also add it to: // isSystem() + // isWakeKey() // frameworks/native/include/android/keycodes.h // frameworks/native/include/input/InputEventLabels.h // frameworks/base/core/res/res/values/attrs.xml diff --git a/core/java/android/view/ViewAnimationUtils.java b/core/java/android/view/ViewAnimationUtils.java index eeff90a..7ced088 100644 --- a/core/java/android/view/ViewAnimationUtils.java +++ b/core/java/android/view/ViewAnimationUtils.java @@ -26,7 +26,7 @@ import android.animation.RevealAnimator; public final class ViewAnimationUtils { private ViewAnimationUtils() {} /** - * Returns a ValueAnimator which can animate a clipping circle. + * Returns an Animator which can animate a clipping circle. * * Any shadow cast by the View will respect the circular clip from this animator. * diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java index 8cae27b..4d2f57a 100644 --- a/core/java/android/view/inputmethod/BaseInputConnection.java +++ b/core/java/android/view/inputmethod/BaseInputConnection.java @@ -429,25 +429,10 @@ public class BaseInputConnection implements InputConnection { } /** - * The default implementation is responsible for handling - * {@link CursorAnchorInfoRequest#TYPE_CURSOR_RECT}. In fact, for derived classes, calling - * {@code super.requestCursorAnchorInfo(request)} is the only way to handle - * {@link CursorAnchorInfoRequest#TYPE_CURSOR_RECT}. + * The default implementation does nothing. */ - public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) { - // This implementation supports TYPE_CURSOR_RECT only. - if (request == null || - request.getRequestType() != CursorAnchorInfoRequest.TYPE_CURSOR_RECT) { - return CursorAnchorInfoRequest.RESULT_NOT_HANDLED; - } - if (mIMM == null) { - // In this case, TYPE_CURSOR_RECT is not handled. - // TODO: Return some notification code for the input method that indicates - // Cursor rect information is temporarily unavailable. - return CursorAnchorInfoRequest.RESULT_NOT_HANDLED; - } - mIMM.setCursorRectMonitorMode(request.getRequestFlags()); - return CursorAnchorInfoRequest.RESULT_SCHEDULED; + public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) { + return false; } /** diff --git a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java b/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java deleted file mode 100644 index e4c94f2..0000000 --- a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2014 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 android.view.inputmethod; - -import android.inputmethodservice.InputMethodService; -import android.os.Parcel; -import android.os.Parcelable; -import android.view.View; - -/** - * Used to enable or disable event notification for - * {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}. This class is also used to - * enable {@link InputMethodService#onUpdateCursor(android.graphics.Rect)} for existing editors - * that have not supported {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}. - */ -public final class CursorAnchorInfoRequest implements Parcelable { - private final int mRequestType; - private final int mRequestFlags; - - /** - * Not handled by the editor. - */ - public static final int RESULT_NOT_HANDLED = 0x00; - /** - * Request is scheduled in the editor task queue. - */ - public static final int RESULT_SCHEDULED = 0x01; - - /** - * The request is for {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}. - * This mechanism is powerful enough to retrieve fine-grained positional information of - * characters in the editor. - */ - public static final int TYPE_CURSOR_ANCHOR_INFO = 0x01; - /** - * The editor is requested to call - * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} - * whenever cursor/anchor position is changed. To disable monitoring, call - * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} again with - * {@link #TYPE_CURSOR_ANCHOR_INFO} and this flag off. - * <p> - * This flag can be used together with {@link #FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE}. - * </p> - */ - public static final int FLAG_CURSOR_ANCHOR_INFO_MONITOR = 0x01; - /** - * The editor is requested to call - * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} at - * once, as soon as possible, regardless of cursor/anchor position changes. This flag can be - * used together with {@link #FLAG_CURSOR_ANCHOR_INFO_MONITOR}. - */ - public static final int FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE = 0x02; - - /** - * The request is for {@link InputMethodService#onUpdateCursor(android.graphics.Rect)}. This - * mechanism has been available since API Level 3 (CUPCAKE) but only the cursor rectangle can - * be retrieved with this mechanism. - */ - public static final int TYPE_CURSOR_RECT = 0x02; - /** - * The editor is requested to call - * {@link InputMethodManager#updateCursor(android.view.View, int, int, int, int)} - * whenever the cursor position is changed. To disable monitoring, call - * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} again with - * {@link #TYPE_CURSOR_RECT} and this flag off. - * <p> - * This flag can be used together with {@link #FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES}. - * </p> - */ - public static final int FLAG_CURSOR_RECT_MONITOR = 0x01; - /** - * {@link InputMethodManager#updateCursor(android.view.View, int, int, int, int)} should be - * called back in screen coordinates. To receive cursor position in local coordinates, call - * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} again with - * {@link #TYPE_CURSOR_RECT} and this flag off. - */ - public static final int FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES = 0x02; - /** - * {@link InputMethodManager#updateCursor(android.view.View, int, int, int, int)} should be - * called back in screen coordinates after coordinate conversion with {@link View#getMatrix()}. - * To disable coordinate conversion with {@link View#getMatrix()} again, call - * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} with - * {@link #TYPE_CURSOR_RECT} and this flag off. - * - * <p> - * The flag is ignored if {@link #FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES} is off. - * </p> - */ - public static final int FLAG_CURSOR_RECT_WITH_VIEW_MATRIX = 0x04; - - /** - * Constructs the object with request type and type-specific flags. - * - * @param requestType the type of this request. Currently {@link #TYPE_CURSOR_ANCHOR_INFO} or - * {@link #TYPE_CURSOR_RECT} is supported. - * @param requestFlags the flags for the given request type. - */ - public CursorAnchorInfoRequest(int requestType, int requestFlags) { - mRequestType = requestType; - mRequestFlags = requestFlags; - } - - /** - * Used to make this class parcelable. - * - * @param source the parcel from which the object is unmarshalled. - */ - public CursorAnchorInfoRequest(Parcel source) { - mRequestType = source.readInt(); - mRequestFlags = source.readInt(); - } - - /** - * @return the type of this request. - */ - public int getRequestType() { - return mRequestType; - } - - /** - * @return the flags that are specific to the type of this request. - */ - public int getRequestFlags() { - return mRequestFlags; - } - - /** - * Used to package this object into a {@link Parcel}. - * - * @param dest The {@link Parcel} to be written. - * @param flags The flags used for parceling. - */ - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mRequestType); - dest.writeInt(mRequestFlags); - } - - @Override - public int hashCode(){ - return mRequestType * 31 + mRequestFlags; - } - - @Override - public boolean equals(Object obj){ - if (obj == null) { - return false; - } - if (this == obj) { - return true; - } - if (!(obj instanceof CursorAnchorInfoRequest)) { - return false; - } - final CursorAnchorInfoRequest that = (CursorAnchorInfoRequest) obj; - if (hashCode() != that.hashCode()) { - return false; - } - return mRequestType != that.mRequestType && mRequestFlags == that.mRequestFlags; - } - - @Override - public String toString() { - return "CursorAnchorInfoRequest{mRequestType=" + mRequestType - + " mRequestFlags=" + mRequestFlags - + "}"; - } - - /** - * Used to make this class parcelable. - */ - public static final Parcelable.Creator<CursorAnchorInfoRequest> CREATOR = - new Parcelable.Creator<CursorAnchorInfoRequest>() { - @Override - public CursorAnchorInfoRequest createFromParcel(Parcel source) { - return new CursorAnchorInfoRequest(source); - } - - @Override - public CursorAnchorInfoRequest[] newArray(int size) { - return new CursorAnchorInfoRequest[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } -} diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java index dff91dc..ca094c1 100644 --- a/core/java/android/view/inputmethod/InputConnection.java +++ b/core/java/android/view/inputmethod/InputConnection.java @@ -725,13 +725,34 @@ public interface InputConnection { public boolean performPrivateCommand(String action, Bundle data); /** - * Called by the IME to ask the editor for calling back + * The editor is requested to call + * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} at + * once, as soon as possible, regardless of cursor/anchor position changes. This flag can be + * used together with {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR}. + */ + public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE = 1 << 0; + + /** + * The editor is requested to call + * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} + * whenever cursor/anchor position is changed. To disable monitoring, call + * {@link InputConnection#requestUpdateCursorAnchorInfo(int)} again with this flag off. + * <p> + * This flag can be used together with {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE}. + * </p> + */ + public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR = 1 << 1; + + /** + * Called by the input method to ask the editor for calling back * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} to * notify cursor/anchor locations. * - * @param request the details of the request. - * @return a result code that depends on {@link CursorAnchorInfoRequest#getRequestType()}. See - * {@link CursorAnchorInfoRequest} for details. + * @param cursorUpdateMode {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE} and/or + * {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR} + * @return {@code true} if the request is scheduled. {@code false} to indicate that when the + * application will not call + * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}. */ - public int requestCursorAnchorInfo(CursorAnchorInfoRequest request); + public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode); } diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java index c831d7c..d95df25 100644 --- a/core/java/android/view/inputmethod/InputConnectionWrapper.java +++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java @@ -126,7 +126,7 @@ public class InputConnectionWrapper implements InputConnection { return mTarget.performPrivateCommand(action, data); } - public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) { - return mTarget.requestCursorAnchorInfo(request); + public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) { + return mTarget.requestUpdateCursorAnchorInfo(cursorUpdateMode); } } diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index eec3570..0a472c7 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -313,9 +313,8 @@ public final class InputMethodManager { CompletionInfo[] mCompletions; // Cursor position on the screen. - Rect mNextCursorRect = new Rect(); + Rect mTmpCursorRect = new Rect(); Rect mCursorRect = new Rect(); - RectF mTempRectF = new RectF(); int mCursorSelStart; int mCursorSelEnd; int mCursorCandStart; @@ -372,28 +371,12 @@ public final class InputMethodManager { InputChannel mCurChannel; ImeInputEventSender mCurSender; - private static final int CURSOR_RECT_MONITOR_MODE_NONE = 0x0; - - private static final int CURSOR_RECT_MONITOR_FLAG_MASK = - CursorAnchorInfoRequest.FLAG_CURSOR_RECT_MONITOR | - CursorAnchorInfoRequest.FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES | - CursorAnchorInfoRequest.FLAG_CURSOR_RECT_WITH_VIEW_MATRIX; - - private static final int CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE = 0x0; - - private static final int CURSOR_ANCHOR_INFO_MONITOR_FLAG_MASK = - CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_MONITOR | - CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE; - - /** - * The monitor mode for {@link #updateCursor(View, int, int, int, int)}. - */ - private int mCursorRectMonitorMode = CURSOR_RECT_MONITOR_MODE_NONE; + private static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE = 0x0; /** * The monitor mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}. */ - private int mCursorAnchorInfoMonitorMode = CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE; + private int mRequestUpdateCursorAnchorInfoMonitorMode = REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE; final Pool<PendingEvent> mPendingEventPool = new SimplePool<PendingEvent>(20); final SparseArray<PendingEvent> mPendingEvents = new SparseArray<PendingEvent>(20); @@ -446,8 +429,8 @@ public final class InputMethodManager { return; } - mCursorAnchorInfoMonitorMode = CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE; - mCursorRectMonitorMode = CURSOR_RECT_MONITOR_MODE_NONE; + mRequestUpdateCursorAnchorInfoMonitorMode = + REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE; setInputChannelLocked(res.channel); mCurMethod = res.method; @@ -1540,59 +1523,49 @@ public final class InputMethodManager { } /** - * Returns true if the current input method wants to watch the location + * Return true if the current input method wants to watch the location * of the input editor's cursor in its window. - */ - public boolean isWatchingCursor(View view) { - if (!isActive(view)) { - return false; - } - synchronized (mH) { - return (mCursorRectMonitorMode & CursorAnchorInfoRequest.FLAG_CURSOR_RECT_MONITOR) != 0; - } - } - - /** - * Updates the result of {@link #isWatchingCursor(View)}. * - * @hide + * @deprecated Use {@link InputConnection#requestUpdateCursorAnchorInfo(int)} instead. */ - public void setCursorRectMonitorMode(int flags) { - synchronized (mH) { - mCursorRectMonitorMode = (CURSOR_RECT_MONITOR_FLAG_MASK & flags); - } + @Deprecated + public boolean isWatchingCursor(View view) { + return false; } /** - * Returns true if the current input method wants to be notified when cursor/anchor location + * Return true if the current input method wants to be notified when cursor/anchor location * is changed. * * @hide */ public boolean isCursorAnchorInfoEnabled() { synchronized (mH) { - final boolean isImmediate = (mCursorAnchorInfoMonitorMode & - CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0; - final boolean isMonitoring = (mCursorAnchorInfoMonitorMode & - CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_MONITOR) != 0; + final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode & + InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0; + final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode & + InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR) != 0; return isImmediate || isMonitoring; } } /** - * Updates the result of {@link #isWatchingCursor(View)}. + * Set the requested mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}. * * @hide */ - public void setCursorAnchorInfoMonitorMode(int flags) { + public void setUpdateCursorAnchorInfoMode(int flags) { synchronized (mH) { - mCursorAnchorInfoMonitorMode = (CURSOR_ANCHOR_INFO_MONITOR_FLAG_MASK & flags); + mRequestUpdateCursorAnchorInfoMonitorMode = flags; } } /** * Report the current cursor location in its window. + * + * @deprecated Use {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)} instead. */ + @Deprecated public void updateCursor(View view, int left, int top, int right, int bottom) { checkFocus(); synchronized (mH) { @@ -1601,33 +1574,15 @@ public final class InputMethodManager { || mCurrentTextBoxAttribute == null || mCurMethod == null) { return; } - if (DEBUG) Log.d(TAG, "updateCursor"); - final boolean usesScreenCoordinates = (mCursorRectMonitorMode & - CursorAnchorInfoRequest.FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES) != 0; - if (usesScreenCoordinates) { - view.getLocationOnScreen(mViewTopLeft); - final Matrix viewMatrix = view.getMatrix(); - final boolean usesViewMatrix = (viewMatrix != null) && ((mCursorRectMonitorMode & - CursorAnchorInfoRequest.FLAG_CURSOR_RECT_WITH_VIEW_MATRIX) != 0); - if (usesViewMatrix) { - mTempRectF.set(left, top, right, bottom); - mViewToScreenMatrix.set(viewMatrix); - mViewToScreenMatrix.postTranslate(mViewTopLeft[0], mViewTopLeft[1]); - mViewToScreenMatrix.mapRect(mTempRectF); - mNextCursorRect.set((int)mTempRectF.left, (int)mTempRectF.top, - (int)mTempRectF.right, (int)mTempRectF.bottom); - } else { - mNextCursorRect.set(left + mViewTopLeft[0], top + mViewTopLeft[1], - right + mViewTopLeft[0], bottom + mViewTopLeft[1]); - } - } else { - mNextCursorRect.set(left, top, right, bottom); - } - if (!Objects.equals(mCursorRect, mNextCursorRect)) { - if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mNextCursorRect); + + mTmpCursorRect.set(left, top, right, bottom); + if (!mCursorRect.equals(mTmpCursorRect)) { + if (DEBUG) Log.d(TAG, "updateCursor"); + try { - mCurMethod.updateCursor(mNextCursorRect); - mCursorRect.set(mNextCursorRect); + if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod); + mCurMethod.updateCursor(mTmpCursorRect); + mCursorRect.set(mTmpCursorRect); } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId, e); } @@ -1652,8 +1607,8 @@ public final class InputMethodManager { } // If immediate bit is set, we will call updateCursorAnchorInfo() even when the data has // not been changed from the previous call. - final boolean isImmediate = (mCursorAnchorInfoMonitorMode & - CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0; + final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode & + InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0; if (!isImmediate && Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) { // TODO: Consider always emitting this message once we have addressed redundant // calls of this method from android.widget.Editor. @@ -1668,8 +1623,8 @@ public final class InputMethodManager { mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo); mCursorAnchorInfo = cursorAnchorInfo; // Clear immediate bit (if any). - mCursorAnchorInfoMonitorMode &= - ~CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE; + mRequestUpdateCursorAnchorInfoMonitorMode &= + ~InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE; } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId, e); } diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 60ef693..eb93745 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -65,7 +65,6 @@ import android.view.animation.LinearInterpolator; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CorrectionInfo; -import android.view.inputmethod.CursorAnchorInfoRequest; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; @@ -5718,8 +5717,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } @Override - public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) { - return getTarget().requestCursorAnchorInfo(request); + public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) { + return getTarget().requestUpdateCursorAnchorInfo(cursorUpdateMode); } } diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 3f5f045..29c8298 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -1298,25 +1298,6 @@ public class Editor { reported = reportExtractedText(); } } - - if (imm.isWatchingCursor(mTextView) && highlight != null) { - highlight.computeBounds(ims.mTmpRectF, true); - ims.mTmpOffset[0] = ims.mTmpOffset[1] = 0; - - canvas.getMatrix().mapPoints(ims.mTmpOffset); - ims.mTmpRectF.offset(ims.mTmpOffset[0], ims.mTmpOffset[1]); - - ims.mTmpRectF.offset(0, cursorOffsetVertical); - - ims.mCursorRectInWindow.set((int)(ims.mTmpRectF.left + 0.5), - (int)(ims.mTmpRectF.top + 0.5), - (int)(ims.mTmpRectF.right + 0.5), - (int)(ims.mTmpRectF.bottom + 0.5)); - - imm.updateCursor(mTextView, - ims.mCursorRectInWindow.left, ims.mCursorRectInWindow.top, - ims.mCursorRectInWindow.right, ims.mCursorRectInWindow.bottom); - } } } @@ -4136,7 +4117,6 @@ public class Editor { static class InputMethodState { Rect mCursorRectInWindow = new Rect(); - RectF mTmpRectF = new RectF(); float[] mTmpOffset = new float[2]; ExtractedTextRequest mExtractedTextRequest; final ExtractedText mExtractedText = new ExtractedText(); diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java index 8ee0a1b..cb0c3d0 100644 --- a/core/java/android/widget/VideoView.java +++ b/core/java/android/widget/VideoView.java @@ -230,16 +230,29 @@ public class VideoView extends SurfaceView mTargetState = STATE_IDLE; } + /** + * Sets video path. + * + * @param path the path of the video. + */ public void setVideoPath(String path) { setVideoURI(Uri.parse(path)); } + /** + * Sets video URI. + * + * @param uri the URI of the video. + */ public void setVideoURI(Uri uri) { setVideoURI(uri, null); } /** - * @hide + * Sets video URI using specific headers. + * + * @param uri the URI of the video. + * @param headers the headers for the URI request. */ public void setVideoURI(Uri uri, Map<String, String> headers) { mUri = uri; |