diff options
| -rw-r--r-- | api/current.txt | 18 | ||||
| -rw-r--r-- | api/removed.txt | 7 | ||||
| -rw-r--r-- | api/system-current.txt | 19 | ||||
| -rw-r--r-- | api/system-removed.txt | 7 | ||||
| -rw-r--r-- | core/java/android/app/admin/DeviceAdminReceiver.java | 33 | ||||
| -rw-r--r-- | core/java/android/app/admin/DevicePolicyManager.java | 20 | ||||
| -rw-r--r-- | core/java/android/app/admin/IDevicePolicyManager.aidl | 2 | ||||
| -rw-r--r-- | core/java/android/net/ConnectivityManager.java | 33 | ||||
| -rw-r--r-- | core/java/android/widget/Editor.java | 6 | ||||
| -rw-r--r-- | core/java/android/widget/TextView.java | 31 | ||||
| -rw-r--r-- | core/java/com/android/internal/widget/FloatingToolbar.java | 40 | ||||
| -rw-r--r-- | core/res/AndroidManifest.xml | 5 | ||||
| -rw-r--r-- | core/res/res/values/ids.xml | 1 | ||||
| -rw-r--r-- | core/res/res/values/public.xml | 1 | ||||
| -rw-r--r-- | graphics/java/android/graphics/Rect.java | 4 | ||||
| -rw-r--r-- | media/java/android/media/MediaCodec.java | 213 | ||||
| -rw-r--r-- | media/java/android/media/MediaCodecInfo.java | 21 | ||||
| -rw-r--r-- | media/java/android/media/tv/TvInputService.java | 4 | ||||
| -rw-r--r-- | services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java | 40 |
19 files changed, 449 insertions, 56 deletions
diff --git a/api/current.txt b/api/current.txt index 0572604bd860..52950fca46e7 100644 --- a/api/current.txt +++ b/api/current.txt @@ -1723,6 +1723,7 @@ package android { field public static final int selectAll = 16908319; // 0x102001f field public static final int selectTextMode = 16908333; // 0x102002d field public static final int selectedIcon = 16908302; // 0x102000e + field public static final int shareText = 16908343; // 0x1020037 field public static final int startSelectingText = 16908328; // 0x1020028 field public static final int statusBarBackground = 16908335; // 0x102002f field public static final int stopSelectingText = 16908329; // 0x1020029 @@ -5651,6 +5652,7 @@ package android.app.admin { method public void onProfileProvisioningComplete(android.content.Context, android.content.Intent); method public void onReadyForUserInitialization(android.content.Context, android.content.Intent); method public void onReceive(android.content.Context, android.content.Intent); + method public void onSystemUpdatePending(android.content.Context, android.content.Intent, long); field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED"; field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED"; field public static final java.lang.String ACTION_DEVICE_ADMIN_ENABLED = "android.app.action.DEVICE_ADMIN_ENABLED"; @@ -15295,7 +15297,9 @@ package android.media { method public final void releaseOutputBuffer(int, boolean); method public final void releaseOutputBuffer(int, long); method public final void reset(); + method public void setCallback(android.media.MediaCodec.Callback, android.os.Handler); method public void setCallback(android.media.MediaCodec.Callback); + method public void setOnFrameRenderedListener(android.media.MediaCodec.OnFrameRenderedListener, android.os.Handler); method public final void setParameters(android.os.Bundle); method public void setSurface(android.view.Surface); method public final void setVideoScalingMode(int); @@ -15366,6 +15370,10 @@ package android.media { field public int numSubSamples; } + public static abstract interface MediaCodec.OnFrameRenderedListener { + method public abstract void onFrameRendered(android.media.MediaCodec, long, long); + } + public final class MediaCodecInfo { method public final android.media.MediaCodecInfo.CodecCapabilities getCapabilitiesForType(java.lang.String); method public final java.lang.String getName(); @@ -15573,6 +15581,7 @@ package android.media { public static final class MediaCodecInfo.VideoCapabilities { method public boolean areSizeAndRateSupported(int, int, double); + method public android.util.Range<java.lang.Double> getAchievableFrameRatesFor(int, int); method public android.util.Range<java.lang.Integer> getBitrateRange(); method public int getHeightAlignment(); method public android.util.Range<java.lang.Integer> getSupportedFrameRates(); @@ -18272,11 +18281,8 @@ package android.net { method public void reportNetworkConnectivity(android.net.Network, boolean); method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback); method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent); - method public deprecated boolean requestRouteToHost(int, int); method public deprecated void setNetworkPreference(int); method public static deprecated boolean setProcessDefaultNetwork(android.net.Network); - method public deprecated int startUsingNetworkFeature(int, java.lang.String); - method public deprecated int stopUsingNetworkFeature(int, java.lang.String); method public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback); field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED"; field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; @@ -18295,9 +18301,9 @@ package android.net { field public static final int TYPE_ETHERNET = 9; // 0x9 field public static final int TYPE_MOBILE = 0; // 0x0 field public static final int TYPE_MOBILE_DUN = 4; // 0x4 - field public static final int TYPE_MOBILE_HIPRI = 5; // 0x5 - field public static final int TYPE_MOBILE_MMS = 2; // 0x2 - field public static final int TYPE_MOBILE_SUPL = 3; // 0x3 + field public static final deprecated int TYPE_MOBILE_HIPRI = 5; // 0x5 + field public static final deprecated int TYPE_MOBILE_MMS = 2; // 0x2 + field public static final deprecated int TYPE_MOBILE_SUPL = 3; // 0x3 field public static final int TYPE_VPN = 17; // 0x11 field public static final int TYPE_WIFI = 1; // 0x1 field public static final int TYPE_WIMAX = 6; // 0x6 diff --git a/api/removed.txt b/api/removed.txt index 326b05de4dd3..a722e176f8fa 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -35,6 +35,13 @@ package android.media { package android.net { + public class ConnectivityManager { + method public deprecated boolean requestRouteToHost(int, int); + method public deprecated boolean requestRouteToHostAddress(int, java.net.InetAddress); + method public deprecated int startUsingNetworkFeature(int, java.lang.String); + method public deprecated int stopUsingNetworkFeature(int, java.lang.String); + } + public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory { method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache); } diff --git a/api/system-current.txt b/api/system-current.txt index 70e4eb147301..7323a9be3ea0 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1800,6 +1800,7 @@ package android { field public static final int selectAll = 16908319; // 0x102001f field public static final int selectTextMode = 16908333; // 0x102002d field public static final int selectedIcon = 16908302; // 0x102000e + field public static final int shareText = 16908343; // 0x1020037 field public static final int startSelectingText = 16908328; // 0x1020028 field public static final int statusBarBackground = 16908335; // 0x102002f field public static final int stopSelectingText = 16908329; // 0x1020029 @@ -5746,6 +5747,7 @@ package android.app.admin { method public void onProfileProvisioningComplete(android.content.Context, android.content.Intent); method public void onReadyForUserInitialization(android.content.Context, android.content.Intent); method public void onReceive(android.content.Context, android.content.Intent); + method public void onSystemUpdatePending(android.content.Context, android.content.Intent, long); field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED"; field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED"; field public static final java.lang.String ACTION_DEVICE_ADMIN_ENABLED = "android.app.action.DEVICE_ADMIN_ENABLED"; @@ -5851,6 +5853,7 @@ package android.app.admin { method public boolean isProfileOwnerApp(java.lang.String); method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String); method public void lockNow(); + method public void notifyPendingSystemUpdate(long); method public void removeActiveAdmin(android.content.ComponentName); method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String); method public boolean removeUser(android.content.ComponentName, android.os.UserHandle); @@ -16507,7 +16510,9 @@ package android.media { method public final void releaseOutputBuffer(int, boolean); method public final void releaseOutputBuffer(int, long); method public final void reset(); + method public void setCallback(android.media.MediaCodec.Callback, android.os.Handler); method public void setCallback(android.media.MediaCodec.Callback); + method public void setOnFrameRenderedListener(android.media.MediaCodec.OnFrameRenderedListener, android.os.Handler); method public final void setParameters(android.os.Bundle); method public void setSurface(android.view.Surface); method public final void setVideoScalingMode(int); @@ -16578,6 +16583,10 @@ package android.media { field public int numSubSamples; } + public static abstract interface MediaCodec.OnFrameRenderedListener { + method public abstract void onFrameRendered(android.media.MediaCodec, long, long); + } + public final class MediaCodecInfo { method public final android.media.MediaCodecInfo.CodecCapabilities getCapabilitiesForType(java.lang.String); method public final java.lang.String getName(); @@ -16785,6 +16794,7 @@ package android.media { public static final class MediaCodecInfo.VideoCapabilities { method public boolean areSizeAndRateSupported(int, int, double); + method public android.util.Range<java.lang.Double> getAchievableFrameRatesFor(int, int); method public android.util.Range<java.lang.Integer> getBitrateRange(); method public int getHeightAlignment(); method public android.util.Range<java.lang.Integer> getSupportedFrameRates(); @@ -19730,11 +19740,8 @@ package android.net { method public void reportNetworkConnectivity(android.net.Network, boolean); method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback); method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent); - method public deprecated boolean requestRouteToHost(int, int); method public deprecated void setNetworkPreference(int); method public static deprecated boolean setProcessDefaultNetwork(android.net.Network); - method public deprecated int startUsingNetworkFeature(int, java.lang.String); - method public deprecated int stopUsingNetworkFeature(int, java.lang.String); method public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback); field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED"; field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; @@ -19753,9 +19760,9 @@ package android.net { field public static final int TYPE_ETHERNET = 9; // 0x9 field public static final int TYPE_MOBILE = 0; // 0x0 field public static final int TYPE_MOBILE_DUN = 4; // 0x4 - field public static final int TYPE_MOBILE_HIPRI = 5; // 0x5 - field public static final int TYPE_MOBILE_MMS = 2; // 0x2 - field public static final int TYPE_MOBILE_SUPL = 3; // 0x3 + field public static final deprecated int TYPE_MOBILE_HIPRI = 5; // 0x5 + field public static final deprecated int TYPE_MOBILE_MMS = 2; // 0x2 + field public static final deprecated int TYPE_MOBILE_SUPL = 3; // 0x3 field public static final int TYPE_VPN = 17; // 0x11 field public static final int TYPE_WIFI = 1; // 0x1 field public static final int TYPE_WIMAX = 6; // 0x6 diff --git a/api/system-removed.txt b/api/system-removed.txt index 326b05de4dd3..a722e176f8fa 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -35,6 +35,13 @@ package android.media { package android.net { + public class ConnectivityManager { + method public deprecated boolean requestRouteToHost(int, int); + method public deprecated boolean requestRouteToHostAddress(int, java.net.InetAddress); + method public deprecated int startUsingNetworkFeature(int, java.lang.String); + method public deprecated int stopUsingNetworkFeature(int, java.lang.String); + } + public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory { method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache); } diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java index fe284ce53137..aea413df5176 100644 --- a/core/java/android/app/admin/DeviceAdminReceiver.java +++ b/core/java/android/app/admin/DeviceAdminReceiver.java @@ -264,6 +264,20 @@ public class DeviceAdminReceiver extends BroadcastReceiver { public static final String EXTRA_CHOOSE_PRIVATE_KEY_RESPONSE = "android.app.extra.CHOOSE_PRIVATE_KEY_RESPONSE"; /** + * Broadcast action: notify device owner that there is a pending system update. + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_NOTIFY_PENDING_SYSTEM_UPDATE = "android.app.action.NOTIFY_PENDING_SYSTEM_UPDATE"; + + /** + * A long type extra for {@link #onSystemUpdatePending} recording the system time as given by + * {@link System#currentTimeMillis()} when the current pending system update is first available. + * @hide + */ + public static final String EXTRA_SYSTEM_UPDATE_RECEIVED_TIME = "android.app.extra.SYSTEM_UPDATE_RECEIVED_TIME"; + + /** * Name under which a DevicePolicy component publishes information * about itself. This meta-data must reference an XML resource containing * a device-admin tag. @@ -486,6 +500,22 @@ public class DeviceAdminReceiver extends BroadcastReceiver { } /** + * Allows the receiver to be notified when information about a pending system update is + * available from the system update service. The same pending system update can trigger multiple + * calls to this method, so it is necessary to examine the incoming parameters for details about + * the update. + * <p> + * This callback is only applicable to device owners. + * + * @param context The running context as per {@link #onReceive}. + * @param intent The received intent as per {@link #onReceive}. + * @param receivedTime The time as given by {@link System#currentTimeMillis()} indicating when + * the current pending update was first available. -1 if no pending update is available. + */ + public void onSystemUpdatePending(Context context, Intent intent, long receivedTime) { + } + + /** * Intercept standard device administrator broadcasts. Implementations * should not override this method; it is better to implement the * convenience callbacks for each action. @@ -530,6 +560,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver { onLockTaskModeExiting(context, intent); } else if (ACTION_READY_FOR_USER_INITIALIZATION.equals(action)) { onReadyForUserInitialization(context, intent); + } else if (ACTION_NOTIFY_PENDING_SYSTEM_UPDATE.equals(action)) { + long receivedTime = intent.getLongExtra(EXTRA_SYSTEM_UPDATE_RECEIVED_TIME, -1); + onSystemUpdatePending(context, intent, receivedTime); } } } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 9e2da61c70f3..a20aa6687069 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -4301,4 +4301,24 @@ public class DevicePolicyManager { Log.w(TAG, "Failed talking with device policy service", re); } } + + /** + * Callable by the system update service to notify device owners about pending updates. + * The caller must hold {@link android.Manifest.permission#NOTIFY_PENDING_SYSTEM_UPDATE} + * permission. + * + * @param updateReceivedTime The time as given by {@link System#currentTimeMillis()} indicating + * when the current pending update was first available. -1 if no update is available. + * @hide + */ + @SystemApi + public void notifyPendingSystemUpdate(long updateReceivedTime) { + if (mService != null) { + try { + mService.notifyPendingSystemUpdate(updateReceivedTime); + } catch (RemoteException re) { + Log.w(TAG, "Could not notify device owner about pending system update", re); + } + } + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 1f7498e9f461..087fc88145f2 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -225,4 +225,6 @@ interface IDevicePolicyManager { boolean setKeyguardEnabledState(in ComponentName admin, boolean enabled); void setStatusBarEnabledState(in ComponentName who, boolean enabled); boolean getDoNotAskCredentialsOnBoot(); + + void notifyPendingSystemUpdate(in long updateReceivedTime); } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index a48b3240673a..63f48cff84c3 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -305,6 +305,9 @@ public class ConnectivityManager { * same network interface as {@link #TYPE_MOBILE} or it may use a different * one. This is used by applications needing to talk to the carrier's * Multimedia Messaging Service servers. + * + * @deprecated Applications should instead use {@link #requestNetwork} to request a network that + * provides the {@link NetworkCapabilities#NET_CAPABILITY_MMS} capability. */ public static final int TYPE_MOBILE_MMS = 2; /** @@ -312,6 +315,9 @@ public class ConnectivityManager { * same network interface as {@link #TYPE_MOBILE} or it may use a different * one. This is used by applications needing to talk to the carrier's * Secure User Plane Location servers for help locating the device. + * + * @deprecated Applications should instead use {@link #requestNetwork} to request a network that + * provides the {@link NetworkCapabilities#NET_CAPABILITY_SUPL} capability. */ public static final int TYPE_MOBILE_SUPL = 3; /** @@ -324,9 +330,10 @@ public class ConnectivityManager { /** * A High Priority Mobile data connection. This network type uses the * same network interface as {@link #TYPE_MOBILE} but the routing setup - * is different. Only requesting processes will have access to the - * Mobile DNS servers and only IP's explicitly requested via {@link #requestRouteToHost} - * will route over this interface if no default route exists. + * is different. + * + * @deprecated Applications should instead use {@link #requestNetwork} to request a network that + * uses the {@link NetworkCapabilities#TRANSPORT_CELLULAR} transport. */ public static final int TYPE_MOBILE_HIPRI = 5; /** @@ -386,7 +393,7 @@ public class ConnectivityManager { */ public static final int TYPE_MOBILE_IA = 14; -/** + /** * Emergency PDN connection for emergency calls * {@hide} */ @@ -736,7 +743,7 @@ public class ConnectivityManager { } /** - * Returns an array of of {@link NetworkCapabilities} objects, representing + * Returns an array of {@link android.net.NetworkCapabilities} objects, representing * the Networks that applications run by the given user will use by default. * @hide */ @@ -826,11 +833,11 @@ public class ConnectivityManager { } /** - * Get the {@link NetworkCapabilities} for the given {@link Network}. This + * Get the {@link android.net.NetworkCapabilities} for the given {@link Network}. This * will return {@code null} if the network is unknown. * * @param network The {@link Network} object identifying the network in question. - * @return The {@link NetworkCapabilities} for the network, or {@code null}. + * @return The {@link android.net.NetworkCapabilities} for the network, or {@code null}. */ public NetworkCapabilities getNetworkCapabilities(Network network) { try { @@ -854,6 +861,7 @@ public class ConnectivityManager { * always indicates failure. * * @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api. + * @removed */ public int startUsingNetworkFeature(int networkType, String feature) { NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature); @@ -901,6 +909,7 @@ public class ConnectivityManager { * always indicates failure. * * @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api. + * @removed */ public int stopUsingNetworkFeature(int networkType, String feature) { NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature); @@ -1179,6 +1188,7 @@ public class ConnectivityManager { * * @deprecated Deprecated in favor of the {@link #requestNetwork}, * {@link #bindProcessToNetwork} and {@link Network#getSocketFactory} api. + * @removed */ public boolean requestRouteToHost(int networkType, int hostAddress) { return requestRouteToHostAddress(networkType, NetworkUtils.intToInetAddress(hostAddress)); @@ -1197,6 +1207,7 @@ public class ConnectivityManager { * @hide * @deprecated Deprecated in favor of the {@link #requestNetwork} and * {@link #bindProcessToNetwork} api. + * @removed */ public boolean requestRouteToHostAddress(int networkType, InetAddress hostAddress) { try { @@ -2057,7 +2068,7 @@ public class ConnectivityManager { * changes capabilities but still satisfies the stated need. * * @param network The {@link Network} whose capabilities have changed. - * @param networkCapabilities The new {@link NetworkCapabilities} for this network. + * @param networkCapabilities The new {@link android.net.NetworkCapabilities} for this network. */ public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {} @@ -2299,7 +2310,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link NetworkCapabilities}. + * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. * * This {@link NetworkRequest} will live until released via * {@link #unregisterNetworkCallback} or the calling application exits. @@ -2318,7 +2329,7 @@ public class ConnectivityManager { } /** - * Request a network to satisfy a set of {@link NetworkCapabilities}, limited + * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited * by a timeout. * * This function behaves identically to the non-timedout version, but if a suitable @@ -2365,7 +2376,7 @@ public class ConnectivityManager { /** - * Request a network to satisfy a set of {@link NetworkCapabilities}. + * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}. * * This function behaves identically to the version that takes a NetworkCallback, but instead * of {@link NetworkCallback} a {@link PendingIntent} is used. This means diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 954fc1de46a8..b049e494f933 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -3079,6 +3079,12 @@ public class Editor { MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); } + if (mTextView.canShare()) { + menu.add(0, TextView.ID_SHARE, 0, com.android.internal.R.string.share). + setShowAsAction( + MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); + } + menu.add(0, TextView.ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll). setAlphabeticShortcut('a'). setShowAsAction( diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 726b89a23f77..3e8df0857b0c 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -8955,13 +8955,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener static final int ID_CUT = android.R.id.cut; static final int ID_COPY = android.R.id.copy; static final int ID_PASTE = android.R.id.paste; + static final int ID_SHARE = android.R.id.shareText; static final int ID_PASTE_AS_PLAIN_TEXT = android.R.id.pasteAsPlainText; static final int ID_REPLACE = android.R.id.replaceText; /** * Called when a context menu option for the text view is selected. Currently * this will be one of {@link android.R.id#selectAll}, {@link android.R.id#cut}, - * {@link android.R.id#copy} or {@link android.R.id#paste}. + * {@link android.R.id#copy}, {@link android.R.id#paste} or {@link android.R.id#shareText}. * * @return true if the context menu item action was performed. */ @@ -9014,6 +9015,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener setPrimaryClip(ClipData.newPlainText(null, getTransformedText(min, max))); stopSelectionActionMode(); return true; + + case ID_SHARE: + shareSelectedText(); + return true; } return false; } @@ -9091,15 +9096,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * If provided, this ActionMode.Callback will be used to create the ActionMode when text * selection is initiated in this View. * - * The standard implementation populates the menu with a subset of Select All, Cut, Copy and - * Paste actions, depending on what this View supports. + * The standard implementation populates the menu with a subset of Select All, Cut, Copy, + * Paste and Share actions, depending on what this View supports. * * A custom implementation can add new entries in the default menu in its * {@link android.view.ActionMode.Callback#onPrepareActionMode(ActionMode, Menu)} method. The * default actions can also be removed from the menu using * {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll}, - * {@link android.R.id#cut}, {@link android.R.id#copy} or {@link android.R.id#paste} ids as - * parameters. + * {@link android.R.id#cut}, {@link android.R.id#copy}, {@link android.R.id#paste} or + * {@link android.R.id#shareText} ids as parameters. * * Returning false from * {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, Menu)} will prevent @@ -9168,6 +9173,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return false; } + boolean canShare() { + return canCopy(); + } + boolean canPaste() { return (mText instanceof Editable && mEditor != null && mEditor.mKeyListener != null && @@ -9241,6 +9250,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } + private void shareSelectedText() { + String selectedText = getSelectedText(); + if (selectedText != null && !selectedText.isEmpty()) { + Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); + sharingIntent.setType("text/plain"); + sharingIntent.removeExtra(android.content.Intent.EXTRA_TEXT); + sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, selectedText); + getContext().startActivity(Intent.createChooser(sharingIntent, null)); + stopSelectionActionMode(); + } + } + private void setPrimaryClip(ClipData clip) { ClipboardManager clipboard = (ClipboardManager) getContext(). getSystemService(Context.CLIPBOARD_SERVICE); diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index a14e98d61f2e..579cad42c68b 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -346,6 +346,17 @@ public final class FloatingToolbar { }; private final Region mTouchableRegion = new Region(); + private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer = + new ViewTreeObserver.OnComputeInternalInsetsListener() { + public void onComputeInternalInsets( + ViewTreeObserver.InternalInsetsInfo info) { + info.contentInsets.setEmpty(); + info.visibleInsets.setEmpty(); + info.touchableRegion.set(mTouchableRegion); + info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo + .TOUCHABLE_INSETS_REGION); + } + }; private boolean mDismissed = true; // tracks whether this popup is dismissed or dismissing. private boolean mHidden; // tracks whether this popup is hidden or hiding. @@ -382,21 +393,6 @@ public final class FloatingToolbar { mPopupWindow.dismiss(); } }); - // Make the touchable area of this popup be the area specified by mTouchableRegion. - mPopupWindow.getContentView() - .getRootView() - .getViewTreeObserver() - .addOnComputeInternalInsetsListener( - new ViewTreeObserver.OnComputeInternalInsetsListener() { - public void onComputeInternalInsets( - ViewTreeObserver.InternalInsetsInfo info) { - info.contentInsets.setEmpty(); - info.visibleInsets.setEmpty(); - info.touchableRegion.set(mTouchableRegion); - info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo - .TOUCHABLE_INSETS_REGION); - } - }); mMarginHorizontal = parent.getResources() .getDimensionPixelSize(R.dimen.floating_toolbar_horizontal_margin); mMarginVertical = parent.getResources() @@ -447,6 +443,7 @@ public final class FloatingToolbar { // The "show" animation will make this visible. mContentContainer.setAlpha(0); mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, x, y); + setTouchableSurfaceInsetsComputer(); runShowAnimation(); } @@ -804,6 +801,19 @@ public final class FloatingToolbar { (int) mContentContainer.getX() + width, (int) mContentContainer.getY() + height); } + + /** + * Make the touchable area of this popup be the area specified by mTouchableRegion. + * This should be called after the popup window has been dismissed (dismiss/hide) + * and is probably being re-shown with a new content root view. + */ + private void setTouchableSurfaceInsetsComputer() { + ViewTreeObserver viewTreeObserver = mPopupWindow.getContentView() + .getRootView() + .getViewTreeObserver(); + viewTreeObserver.removeOnComputeInternalInsetsListener(mInsetsComputer); + viewTreeObserver.addOnComputeInternalInsetsListener(mInsetsComputer); + } } /** diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index fa5e4ad93044..62685a1898f7 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1116,6 +1116,11 @@ <permission android:name="android.permission.ACCESS_PDB_STATE" android:protectionLevel="signature" /> + <!-- @hide Allows system update service to notify device owner about pending updates. + <p>Not for use by third-party applications. --> + <permission android:name="android.permission.NOTIFY_PENDING_SYSTEM_UPDATE" + android:protectionLevel="signatureOrSystem" /> + <!-- =========================================== --> <!-- Permissions associated with camera and image capture --> <!-- =========================================== --> diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml index aaf252a8e974..bdc8d9fa4054 100644 --- a/core/res/res/values/ids.xml +++ b/core/res/res/values/ids.xml @@ -93,6 +93,7 @@ <item type="id" name="undo" /> <item type="id" name="redo" /> <item type="id" name="replaceText" /> + <item type="id" name="shareText" /> <!-- Accessibility action identifier for {@link android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_SHOW_ON_SCREEN}. --> <item type="id" name="accessibilityActionShowOnScreen" /> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 7252584c9b18..0b4320c45133 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2650,6 +2650,7 @@ <public type="id" name="replaceText" /> <public type="id" name="accessibilityActionShowOnScreen" /> <public type="id" name="accessibilityActionScrollToPosition" /> + <public type="id" name="shareText" /> <public type="attr" name="allowUndo" /> <public type="attr" name="colorBackgroundFloating" /> diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java index a9a8f37c6dae..f036b19d22c3 100644 --- a/graphics/java/android/graphics/Rect.java +++ b/graphics/java/android/graphics/Rect.java @@ -16,6 +16,7 @@ package android.graphics; +import android.annotation.CheckResult; import android.os.Parcel; import android.os.Parcelable; @@ -389,6 +390,7 @@ public final class Rect implements Parcelable { * (and this rectangle is then set to that intersection) else * return false and do not change this rectangle. */ + @CheckResult public boolean intersect(int left, int top, int right, int bottom) { if (this.left < right && left < this.right && this.top < bottom && top < this.bottom) { if (this.left < left) this.left = left; @@ -411,6 +413,7 @@ public final class Rect implements Parcelable { * (and this rectangle is then set to that intersection) else * return false and do not change this rectangle. */ + @CheckResult public boolean intersect(Rect r) { return intersect(r.left, r.top, r.right, r.bottom); } @@ -427,6 +430,7 @@ public final class Rect implements Parcelable { * this rectangle to that intersection. If they do not, return * false and do not change this rectangle. */ + @CheckResult public boolean setIntersect(Rect a, Rect b) { if (a.left < b.right && b.left < a.right && a.top < b.bottom && b.top < a.bottom) { left = Math.max(a.left, b.left); diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 680c3769e8ed..1f00c7b03090 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -300,6 +300,14 @@ final public class MediaCodec { */ @BufferFlag public int flags; + + /** @hide */ + @NonNull + public BufferInfo dup() { + BufferInfo copy = new BufferInfo(); + copy.set(offset, size, presentationTimeUs, flags); + return copy; + } }; // The follow flag constants MUST stay in sync with their equivalents @@ -343,11 +351,25 @@ final public class MediaCodec { @Retention(RetentionPolicy.SOURCE) public @interface BufferFlag {} + private static class FrameRenderedInfo { + public long mPresentationTimeUs; + public long mNanoTime; + public FrameRenderedInfo(long presentationTimeUs, long nanoTime) { + mPresentationTimeUs = presentationTimeUs; + mNanoTime = nanoTime; + } + } + private EventHandler mEventHandler; + private EventHandler mOnFrameRenderedHandler; + private EventHandler mCallbackHandler; private Callback mCallback; + private OnFrameRenderedListener mOnFrameRenderedListener; + private Object mListenerLock = new Object(); private static final int EVENT_CALLBACK = 1; private static final int EVENT_SET_CALLBACK = 2; + private static final int EVENT_FRAME_RENDERED = 3; private static final int CB_INPUT_AVAILABLE = 1; private static final int CB_OUTPUT_AVAILABLE = 2; @@ -375,6 +397,15 @@ final public class MediaCodec { mCallback = (MediaCodec.Callback) msg.obj; break; } + case EVENT_FRAME_RENDERED: + synchronized (mListenerLock) { + FrameRenderedInfo info = (FrameRenderedInfo)msg.obj; + if (mOnFrameRenderedListener != null) { + mOnFrameRenderedListener.onFrameRendered( + mCodec, info.mPresentationTimeUs, info.mNanoTime); + } + break; + } default: { break; @@ -431,6 +462,8 @@ final public class MediaCodec { } } + private boolean mHasSurface = false; + /** * Instantiate a decoder supporting input data of the given mime type. * @@ -501,6 +534,9 @@ final public class MediaCodec { } else { mEventHandler = null; } + mCallbackHandler = mEventHandler; + mOnFrameRenderedHandler = mEventHandler; + mBufferLock = new Object(); native_setup(name, nameIsType, encoder); @@ -607,6 +643,8 @@ final public class MediaCodec { } } + mHasSurface = surface != null; + native_configure(keys, values, surface, crypto, flags); } @@ -717,9 +755,14 @@ final public class MediaCodec { native_stop(); freeAllTrackedBuffers(); - if (mEventHandler != null) { - mEventHandler.removeMessages(EVENT_CALLBACK); - mEventHandler.removeMessages(EVENT_SET_CALLBACK); + synchronized (mListenerLock) { + if (mCallbackHandler != null) { + mCallbackHandler.removeMessages(EVENT_SET_CALLBACK); + mCallbackHandler.removeMessages(EVENT_CALLBACK); + } + if (mOnFrameRenderedHandler != null) { + mOnFrameRenderedHandler.removeMessages(EVENT_FRAME_RENDERED); + } } } @@ -1179,6 +1222,9 @@ final public class MediaCodec { cacheBuffers(false /* input */); } else if (res >= 0) { validateOutputByteBuffer(mCachedOutputBuffers, res, info); + if (mHasSurface) { + mDequeuedOutputInfos.put(res, info.dup()); + } } } return res; @@ -1205,13 +1251,34 @@ final public class MediaCodec { * @throws MediaCodec.CodecException upon codec error. */ public final void releaseOutputBuffer(int index, boolean render) { + BufferInfo info = null; synchronized(mBufferLock) { invalidateByteBuffer(mCachedOutputBuffers, index); mDequeuedOutputBuffers.remove(index); + if (mHasSurface) { + info = mDequeuedOutputInfos.remove(index); + } } + // TODO + // until codec and libgui supports callback, assume frame is rendered within 50 ms + postRenderedCallback(render, info, 50 /* delayMs */); releaseOutputBuffer(index, render, false /* updatePTS */, 0 /* dummy */); } + private void postRenderedCallback(boolean render, @Nullable BufferInfo info, long delayMs) { + if (render && info != null) { + synchronized (mListenerLock) { + if (mOnFrameRenderedListener != null) { + FrameRenderedInfo obj = new FrameRenderedInfo( + info.presentationTimeUs, System.nanoTime() + delayMs * 1000000); + Message msg = mOnFrameRenderedHandler.obtainMessage( + EVENT_FRAME_RENDERED, obj); + mOnFrameRenderedHandler.sendMessageDelayed(msg, delayMs); + } + } + } + } + /** * If you are done with a buffer, use this call to update its surface timestamp * and return it to the codec to render it on the output surface. If you @@ -1262,10 +1329,20 @@ final public class MediaCodec { * @throws MediaCodec.CodecException upon codec error. */ public final void releaseOutputBuffer(int index, long renderTimestampNs) { + BufferInfo info = null; synchronized(mBufferLock) { invalidateByteBuffer(mCachedOutputBuffers, index); mDequeuedOutputBuffers.remove(index); + if (mHasSurface) { + info = mDequeuedOutputInfos.remove(index); + } } + // TODO + // until codec and libgui supports callback, assume frame is rendered at the + // render time or 16 ms from now, whichever is later. + postRenderedCallback( + true /* render */, info, + Math.max(renderTimestampNs - System.nanoTime(), 16666666) / 1000000); releaseOutputBuffer( index, true /* render */, true /* updatePTS */, renderTimestampNs); } @@ -1405,6 +1482,8 @@ final public class MediaCodec { private ByteBuffer[] mCachedOutputBuffers; private final BufferMap mDequeuedInputBuffers = new BufferMap(); private final BufferMap mDequeuedOutputBuffers = new BufferMap(); + private final Map<Integer, BufferInfo> mDequeuedOutputInfos = + new HashMap<Integer, BufferInfo>(); final private Object mBufferLock; private final void invalidateByteBuffer( @@ -1770,21 +1849,121 @@ final public class MediaCodec { * @param cb The callback that will run. Use {@code null} to clear a previously * set callback (before {@link #configure configure} is called and run * in synchronous mode). + * @param handler Callbacks will happen on the handler's thread. If {@code null}, + * callbacks are done on the default thread (the caller's thread or the + * main thread.) */ - public void setCallback(@Nullable /* MediaCodec. */ Callback cb) { - if (mEventHandler != null) { - // set java callback on handler - Message msg = mEventHandler.obtainMessage(EVENT_SET_CALLBACK, 0, 0, cb); - mEventHandler.sendMessage(msg); + public void setCallback(@Nullable /* MediaCodec. */ Callback cb, @Nullable Handler handler) { + if (cb != null) { + synchronized (mListenerLock) { + EventHandler newHandler = getEventHandlerOn(handler, mCallbackHandler); + // NOTE: there are no callbacks on the handler at this time, but check anyways + // even if we were to extend this to be callable dynamically, it must + // be called when codec is flushed, so no messages are pending. + if (newHandler != mCallbackHandler) { + mCallbackHandler.removeMessages(EVENT_SET_CALLBACK); + mCallbackHandler.removeMessages(EVENT_CALLBACK); + mCallbackHandler = newHandler; + } + } + } else if (mCallbackHandler != null) { + mCallbackHandler.removeMessages(EVENT_SET_CALLBACK); + mCallbackHandler.removeMessages(EVENT_CALLBACK); + } + + if (mCallbackHandler != null) { + // set java callback on main handler + Message msg = mCallbackHandler.obtainMessage(EVENT_SET_CALLBACK, 0, 0, cb); + mCallbackHandler.sendMessage(msg); // set native handler here, don't post to handler because - // it may cause the callback to be delayed and set in a wrong state, - // and MediaCodec is already doing it on looper. + // it may cause the callback to be delayed and set in a wrong state. + // Note that native codec may start sending events to the callback + // handler after this returns. native_setCallback(cb); } } /** + * Sets an asynchronous callback for actionable MediaCodec events on the default + * looper. + * <p> + * Same as {@link #setCallback(Callback, Handler)} with handler set to null. + * @param cb The callback that will run. Use {@code null} to clear a previously + * set callback (before {@link #configure configure} is called and run + * in synchronous mode). + * @see #setCallback(Callback, Handler) + */ + public void setCallback(@Nullable /* MediaCodec. */ Callback cb) { + setCallback(cb, null /* handler */); + } + + /** + * Listener to be called when an output frame has rendered on the output surface + * + * @see MediaCodec#setOnFrameRenderedListener + */ + public interface OnFrameRenderedListener { + + /** + * Called when an output frame has rendered on the output surface. + * + * @param codec the MediaCodec instance + * @param presentationTimeUs the presentation time (media time) of the frame rendered. + * This is usually the same as specified in {@link #queueInputBuffer}; however, + * some codecs may alter the media time by applying some time-based transformation, + * such as frame rate conversion. In that case, presentation time corresponds + * to the actual output frame rendered. + * @param nanoTime The system time when the frame was rendered. + * + * @see System#nanoTime + */ + public void onFrameRendered( + @NonNull MediaCodec codec, long presentationTimeUs, long nanoTime); + } + + /** + * Register a callback to be invoked when an output frame is rendered on the output surface. + * <p> + * This method can be called in any codec state, but will only have an effect in the + * Executing state for codecs that render buffers to the output surface. + * + * @param listener the callback that will be run + * @param handler the callback will be run on the handler's thread. If {@code null}, + * the callback will be run on the default thread, which is the looper + * from which the codec was created, or a new thread if there was none. + */ + public void setOnFrameRenderedListener( + @Nullable OnFrameRenderedListener listener, @Nullable Handler handler) { + synchronized (mListenerLock) { + mOnFrameRenderedListener = listener; + if (listener != null) { + EventHandler newHandler = getEventHandlerOn(handler, mOnFrameRenderedHandler); + if (newHandler != mOnFrameRenderedHandler) { + mOnFrameRenderedHandler.removeMessages(EVENT_FRAME_RENDERED); + } + mOnFrameRenderedHandler = newHandler; + } else if (mOnFrameRenderedHandler != null) { + mOnFrameRenderedHandler.removeMessages(EVENT_FRAME_RENDERED); + } + } + } + + private EventHandler getEventHandlerOn( + @Nullable Handler handler, @NonNull EventHandler lastHandler) { + if (handler == null) { + return mEventHandler; + } else { + Looper looper = handler.getLooper(); + if (lastHandler.getLooper() == looper) { + return lastHandler; + } else { + return new EventHandler(this, looper); + } + } + } + + /** * MediaCodec callback interface. Used to notify the user asynchronously * of various MediaCodec events. */ @@ -1827,9 +2006,17 @@ final public class MediaCodec { private void postEventFromNative( int what, int arg1, int arg2, @Nullable Object obj) { - if (mEventHandler != null) { - Message msg = mEventHandler.obtainMessage(what, arg1, arg2, obj); - mEventHandler.sendMessage(msg); + synchronized (mListenerLock) { + EventHandler handler = mEventHandler; + if (what == EVENT_CALLBACK) { + handler = mCallbackHandler; + } else if (what == EVENT_FRAME_RENDERED) { + handler = mOnFrameRenderedHandler; + } + if (handler != null) { + Message msg = handler.obtainMessage(what, arg1, arg2, obj); + handler.sendMessage(msg); + } } } diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index b497001b6d3d..ff1b57d54aaf 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -1136,6 +1136,27 @@ public final class MediaCodecInfo { } /** + * Returns the range of achievable video frame rates for a video size. + * May return {@code null}, if the codec did not publish any measurement + * data. + * <p> + * This is a performance estimate, based on full-speed decoding + * and encoding measurements of common video sizes supported by the codec. + * + * @param width the width of the video + * @param height the height of the video + * + * @throws IllegalArgumentException if the video size is not supported. + */ + public Range<Double> getAchievableFrameRatesFor(int width, int height) { + if (!supports(width, height, null)) { + throw new IllegalArgumentException("unsupported size"); + } + // TODO: get this data from the codec + return null; + } + + /** * Returns whether a given video size ({@code width} and * {@code height}) and {@code frameRate} combination is supported. */ diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index 9bdeb2540e4e..278d627a47c4 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -883,6 +883,10 @@ public abstract class TvInputService extends Service { /** * Called when the application sets playback rate and audio mode. + * <p> + * Once a playback rate is set, the implementation should honor the value until a new tune + * request. Pause/resume/seek request does not reset the playback rate previously set. + * </p> * * @param rate The ratio between desired playback rate and normal one. * @param audioMode Audio playback mode. Must be one of the supported audio modes: diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index dc7fad6c4935..80d075dd57fd 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -22,6 +22,7 @@ import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE; import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA; import static android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES; +import android.Manifest.permission; import android.accessibilityservice.AccessibilityServiceInfo; import android.accounts.AccountManager; import android.app.Activity; @@ -45,6 +46,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; @@ -6088,4 +6090,42 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } return false; } + + @Override + public void notifyPendingSystemUpdate(long updateReceivedTime) { + mContext.enforceCallingOrSelfPermission(permission.NOTIFY_PENDING_SYSTEM_UPDATE, + "Only the system update service can broadcast update information"); + + if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) { + Slog.w(LOG_TAG, "Only the system update service in the primary user" + + "can broadcast update information."); + return; + } + Intent intent = new Intent(DeviceAdminReceiver.ACTION_NOTIFY_PENDING_SYSTEM_UPDATE); + intent.putExtra(DeviceAdminReceiver.EXTRA_SYSTEM_UPDATE_RECEIVED_TIME, + updateReceivedTime); + + synchronized (this) { + String deviceOwnerPackage = getDeviceOwner(); + if (deviceOwnerPackage == null) { + return; + } + + try { + ActivityInfo[] receivers = mContext.getPackageManager().getPackageInfo( + deviceOwnerPackage, PackageManager.GET_RECEIVERS).receivers; + if (receivers != null) { + for (int i = 0; i < receivers.length; i++) { + if (permission.BIND_DEVICE_ADMIN.equals(receivers[i].permission)) { + intent.setComponent(new ComponentName(deviceOwnerPackage, + receivers[i].name)); + mContext.sendBroadcastAsUser(intent, UserHandle.OWNER); + } + } + } + } catch (NameNotFoundException e) { + Log.e(LOG_TAG, "Cannot find device owner package", e); + } + } + } } |