diff options
447 files changed, 8802 insertions, 2526 deletions
@@ -251,10 +251,14 @@ LOCAL_SRC_FILES += \ media/java/android/media/IAudioService.aidl \ media/java/android/media/IAudioFocusDispatcher.aidl \ media/java/android/media/IAudioRoutesObserver.aidl \ + media/java/android/media/IMediaRouterClient.aidl \ + media/java/android/media/IMediaRouterService.aidl \ media/java/android/media/IMediaScannerListener.aidl \ media/java/android/media/IMediaScannerService.aidl \ media/java/android/media/IRemoteControlClient.aidl \ media/java/android/media/IRemoteControlDisplay.aidl \ + media/java/android/media/IRemoteDisplayCallback.aidl \ + media/java/android/media/IRemoteDisplayProvider.aidl \ media/java/android/media/IRemoteVolumeObserver.aidl \ media/java/android/media/IRingtonePlayer.aidl \ telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \ diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index c18f542..0344d26 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -107,7 +107,7 @@ public class Am extends BaseCommand { " am switch-user <USER_ID>\n" + " am stop-user <USER_ID>\n" + " am stack create <TASK_ID> <RELATIVE_STACK_BOX_ID> <POSITION> <WEIGHT>\n" + - " am stack movetask <STACK_ID> <TASK_ID> [true|false]\n" + + " am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" + " am stack resize <STACK_ID> <WEIGHT>\n" + " am stack boxes\n" + " am stack box <STACK_BOX_ID>\n" + diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index bb04063..7ca3459 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -2272,9 +2272,12 @@ public class ActivityManager { public static void dumpPackageStateStatic(FileDescriptor fd, String packageName) { FileOutputStream fout = new FileOutputStream(fd); PrintWriter pw = new FastPrintWriter(fout); - dumpService(pw, fd, Context.ACTIVITY_SERVICE, new String[] { "package", packageName }); + dumpService(pw, fd, Context.ACTIVITY_SERVICE, new String[] { + "-a", "package", packageName }); pw.println(); - dumpService(pw, fd, ProcessStats.SERVICE_NAME, new String[] { packageName }); + dumpService(pw, fd, "meminfo", new String[] { "--local", packageName }); + pw.println(); + dumpService(pw, fd, ProcessStats.SERVICE_NAME, new String[] { "-a", packageName }); pw.println(); dumpService(pw, fd, "usagestats", new String[] { "--packages", packageName }); pw.println(); @@ -2296,7 +2299,7 @@ public class ActivityManager { pw.flush(); tp = new TransferPipe(); tp.setBufferPrefix(" "); - service.dump(tp.getWriteFd().getFileDescriptor(), args); + service.dumpAsync(tp.getWriteFd().getFileDescriptor(), args); tp.go(fd); } catch (Throwable e) { if (tp != null) { diff --git a/core/java/android/app/MediaRouteActionProvider.java b/core/java/android/app/MediaRouteActionProvider.java index 63b641c..dffa969 100644 --- a/core/java/android/app/MediaRouteActionProvider.java +++ b/core/java/android/app/MediaRouteActionProvider.java @@ -16,10 +16,7 @@ package android.app; -import com.android.internal.app.MediaRouteChooserDialogFragment; - import android.content.Context; -import android.content.ContextWrapper; import android.media.MediaRouter; import android.media.MediaRouter.RouteInfo; import android.util.Log; @@ -30,22 +27,38 @@ import android.view.ViewGroup; import java.lang.ref.WeakReference; +/** + * The media route action provider displays a {@link MediaRouteButton media route button} + * in the application's {@link ActionBar} to allow the user to select routes and + * to control the currently selected route. + * <p> + * The application must specify the kinds of routes that the user should be allowed + * to select by specifying the route types with the {@link #setRouteTypes} method. + * </p><p> + * Refer to {@link MediaRouteButton} for a description of the button that will + * appear in the action bar menu. Note that instead of disabling the button + * when no routes are available, the action provider will instead make the + * menu item invisible. In this way, the button will only be visible when it + * is possible for the user to discover and select a matching route. + * </p> + */ public class MediaRouteActionProvider extends ActionProvider { private static final String TAG = "MediaRouteActionProvider"; - private Context mContext; - private MediaRouter mRouter; - private MenuItem mMenuItem; - private MediaRouteButton mView; + private final Context mContext; + private final MediaRouter mRouter; + private final MediaRouterCallback mCallback; + private int mRouteTypes; + private MediaRouteButton mButton; private View.OnClickListener mExtendedSettingsListener; - private RouterCallback mCallback; public MediaRouteActionProvider(Context context) { super(context); + mContext = context; mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE); - mCallback = new RouterCallback(this); + mCallback = new MediaRouterCallback(this); // Start with live audio by default. // TODO Update this when new route types are added; segment by API level @@ -53,80 +66,74 @@ public class MediaRouteActionProvider extends ActionProvider { setRouteTypes(MediaRouter.ROUTE_TYPE_LIVE_AUDIO); } + /** + * Sets the types of routes that will be shown in the media route chooser dialog + * launched by this button. + * + * @param types The route types to match. + */ public void setRouteTypes(int types) { - if (mRouteTypes == types) return; - if (mRouteTypes != 0) { - mRouter.removeCallback(mCallback); - } - mRouteTypes = types; - if (types != 0) { - mRouter.addCallback(types, mCallback); + if (mRouteTypes != types) { + // FIXME: We currently have no way of knowing whether the action provider + // is still needed by the UI. Unfortunately this means the action provider + // may leak callbacks until garbage collection occurs. This may result in + // media route providers doing more work than necessary in the short term + // while trying to discover routes that are no longer of interest to the + // application. To solve this problem, the action provider will need some + // indication from the framework that it is being destroyed. + if (mRouteTypes != 0) { + mRouter.removeCallback(mCallback); + } + mRouteTypes = types; + if (types != 0) { + mRouter.addCallback(types, mCallback, + MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY); + } + refreshRoute(); + + if (mButton != null) { + mButton.setRouteTypes(mRouteTypes); + } } - if (mView != null) { - mView.setRouteTypes(mRouteTypes); + } + + public void setExtendedSettingsClickListener(View.OnClickListener listener) { + mExtendedSettingsListener = listener; + if (mButton != null) { + mButton.setExtendedSettingsClickListener(listener); } } @Override + @SuppressWarnings("deprecation") public View onCreateActionView() { throw new UnsupportedOperationException("Use onCreateActionView(MenuItem) instead."); } @Override public View onCreateActionView(MenuItem item) { - if (mMenuItem != null || mView != null) { + if (mButton != null) { Log.e(TAG, "onCreateActionView: this ActionProvider is already associated " + "with a menu item. Don't reuse MediaRouteActionProvider instances! " + "Abandoning the old one..."); } - mMenuItem = item; - mView = new MediaRouteButton(mContext); - mView.setCheatSheetEnabled(true); - mView.setRouteTypes(mRouteTypes); - mView.setExtendedSettingsClickListener(mExtendedSettingsListener); - mView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + + mButton = new MediaRouteButton(mContext); + mButton.setCheatSheetEnabled(true); + mButton.setRouteTypes(mRouteTypes); + mButton.setExtendedSettingsClickListener(mExtendedSettingsListener); + mButton.setLayoutParams(new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT)); - return mView; + return mButton; } @Override public boolean onPerformDefaultAction() { - final FragmentManager fm = getActivity().getFragmentManager(); - // See if one is already attached to this activity. - MediaRouteChooserDialogFragment dialogFragment = - (MediaRouteChooserDialogFragment) fm.findFragmentByTag( - MediaRouteChooserDialogFragment.FRAGMENT_TAG); - if (dialogFragment != null) { - Log.w(TAG, "onPerformDefaultAction(): Chooser dialog already showing!"); - return false; - } - - dialogFragment = new MediaRouteChooserDialogFragment(); - dialogFragment.setExtendedSettingsClickListener(mExtendedSettingsListener); - dialogFragment.setRouteTypes(mRouteTypes); - dialogFragment.show(fm, MediaRouteChooserDialogFragment.FRAGMENT_TAG); - return true; - } - - private Activity getActivity() { - // Gross way of unwrapping the Activity so we can get the FragmentManager - Context context = mContext; - while (context instanceof ContextWrapper && !(context instanceof Activity)) { - context = ((ContextWrapper) context).getBaseContext(); - } - if (!(context instanceof Activity)) { - throw new IllegalStateException("The MediaRouteActionProvider's Context " + - "is not an Activity."); - } - - return (Activity) context; - } - - public void setExtendedSettingsClickListener(View.OnClickListener listener) { - mExtendedSettingsListener = listener; - if (mView != null) { - mView.setExtendedSettingsClickListener(listener); + if (mButton != null) { + return mButton.showDialogInternal(); } + return false; } @Override @@ -136,36 +143,43 @@ public class MediaRouteActionProvider extends ActionProvider { @Override public boolean isVisible() { - return mRouter.getRouteCount() > 1; + return mRouter.isRouteAvailable(mRouteTypes, + MediaRouter.AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE); + } + + private void refreshRoute() { + refreshVisibility(); } - private static class RouterCallback extends MediaRouter.SimpleCallback { - private WeakReference<MediaRouteActionProvider> mAp; + private static class MediaRouterCallback extends MediaRouter.SimpleCallback { + private final WeakReference<MediaRouteActionProvider> mProviderWeak; - RouterCallback(MediaRouteActionProvider ap) { - mAp = new WeakReference<MediaRouteActionProvider>(ap); + public MediaRouterCallback(MediaRouteActionProvider provider) { + mProviderWeak = new WeakReference<MediaRouteActionProvider>(provider); } @Override public void onRouteAdded(MediaRouter router, RouteInfo info) { - final MediaRouteActionProvider ap = mAp.get(); - if (ap == null) { - router.removeCallback(this); - return; - } - - ap.refreshVisibility(); + refreshRoute(router); } @Override public void onRouteRemoved(MediaRouter router, RouteInfo info) { - final MediaRouteActionProvider ap = mAp.get(); - if (ap == null) { + refreshRoute(router); + } + + @Override + public void onRouteChanged(MediaRouter router, RouteInfo info) { + refreshRoute(router); + } + + private void refreshRoute(MediaRouter router) { + MediaRouteActionProvider provider = mProviderWeak.get(); + if (provider != null) { + provider.refreshRoute(); + } else { router.removeCallback(this); - return; } - - ap.refreshVisibility(); } } } diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java index 7e0a27a..a7982f4 100644 --- a/core/java/android/app/MediaRouteButton.java +++ b/core/java/android/app/MediaRouteButton.java @@ -17,7 +17,7 @@ package android.app; import com.android.internal.R; -import com.android.internal.app.MediaRouteChooserDialogFragment; +import com.android.internal.app.MediaRouteDialogPresenter; import android.content.Context; import android.content.ContextWrapper; @@ -30,7 +30,6 @@ import android.media.MediaRouter.RouteGroup; import android.media.MediaRouter.RouteInfo; import android.text.TextUtils; import android.util.AttributeSet; -import android.util.Log; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.SoundEffectConstants; @@ -38,17 +37,15 @@ import android.view.View; import android.widget.Toast; public class MediaRouteButton extends View { - private static final String TAG = "MediaRouteButton"; + private final MediaRouter mRouter; + private final MediaRouterCallback mCallback; - private MediaRouter mRouter; - private final MediaRouteCallback mRouterCallback = new MediaRouteCallback(); private int mRouteTypes; private boolean mAttachedToWindow; private Drawable mRemoteIndicator; private boolean mRemoteActive; - private boolean mToggleMode; private boolean mCheatSheetEnabled; private boolean mIsConnecting; @@ -56,12 +53,13 @@ public class MediaRouteButton extends View { private int mMinHeight; private OnClickListener mExtendedSettingsClickListener; - private MediaRouteChooserDialogFragment mDialogFragment; + // The checked state is used when connected to a remote route. private static final int[] CHECKED_STATE_SET = { R.attr.state_checked }; + // The activated state is used while connecting to a remote route. private static final int[] ACTIVATED_STATE_SET = { R.attr.state_activated }; @@ -78,6 +76,7 @@ public class MediaRouteButton extends View { super(context, attrs, defStyleAttr); mRouter = (MediaRouter)context.getSystemService(Context.MEDIA_ROUTER_SERVICE); + mCallback = new MediaRouterCallback(); TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.MediaRouteButton, defStyleAttr, 0); @@ -98,54 +97,100 @@ public class MediaRouteButton extends View { setRouteTypes(routeTypes); } - private void setRemoteIndicatorDrawable(Drawable d) { - if (mRemoteIndicator != null) { - mRemoteIndicator.setCallback(null); - unscheduleDrawable(mRemoteIndicator); - } - mRemoteIndicator = d; - if (d != null) { - d.setCallback(this); - d.setState(getDrawableState()); - d.setVisible(getVisibility() == VISIBLE, false); + /** + * Gets the media route types for filtering the routes that the user can + * select using the media route chooser dialog. + * + * @return The route types. + */ + public int getRouteTypes() { + return mRouteTypes; + } + + /** + * Sets the types of routes that will be shown in the media route chooser dialog + * launched by this button. + * + * @param types The route types to match. + */ + public void setRouteTypes(int types) { + if (mRouteTypes != types) { + if (mAttachedToWindow && mRouteTypes != 0) { + mRouter.removeCallback(mCallback); + } + + mRouteTypes = types; + + if (mAttachedToWindow && types != 0) { + mRouter.addCallback(types, mCallback, + MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY); + } + + refreshRoute(); } + } - refreshDrawableState(); + public void setExtendedSettingsClickListener(OnClickListener listener) { + mExtendedSettingsClickListener = listener; } - @Override - public boolean performClick() { - // Send the appropriate accessibility events and call listeners - boolean handled = super.performClick(); - if (!handled) { - playSoundEffect(SoundEffectConstants.CLICK); + /** + * Show the route chooser or controller dialog. + * <p> + * If the default route is selected or if the currently selected route does + * not match the {@link #getRouteTypes route types}, then shows the route chooser dialog. + * Otherwise, shows the route controller dialog to offer the user + * a choice to disconnect from the route or perform other control actions + * such as setting the route's volume. + * </p><p> + * This will attach a {@link DialogFragment} to the containing Activity. + * </p> + */ + public void showDialog() { + showDialogInternal(); + } + + boolean showDialogInternal() { + if (!mAttachedToWindow) { + return false; } - if (mToggleMode) { - if (mRemoteActive) { - mRouter.selectRouteInt(mRouteTypes, mRouter.getDefaultRoute()); - } else { - final int N = mRouter.getRouteCount(); - for (int i = 0; i < N; i++) { - final RouteInfo route = mRouter.getRouteAt(i); - if ((route.getSupportedTypes() & mRouteTypes) != 0 && - route != mRouter.getDefaultRoute()) { - mRouter.selectRouteInt(mRouteTypes, route); - } - } + DialogFragment f = MediaRouteDialogPresenter.showDialogFragment(getActivity(), + mRouteTypes, mExtendedSettingsClickListener); + return f != null; + } + + private Activity getActivity() { + // Gross way of unwrapping the Activity so we can get the FragmentManager + Context context = getContext(); + while (context instanceof ContextWrapper) { + if (context instanceof Activity) { + return (Activity)context; } - } else { - showDialog(); + context = ((ContextWrapper)context).getBaseContext(); } - - return handled; + throw new IllegalStateException("The MediaRouteButton's Context is not an Activity."); } + /** + * Sets whether to enable showing a toast with the content descriptor of the + * button when the button is long pressed. + */ void setCheatSheetEnabled(boolean enable) { mCheatSheetEnabled = enable; } @Override + public boolean performClick() { + // Send the appropriate accessibility events and call listeners + boolean handled = super.performClick(); + if (!handled) { + playSoundEffect(SoundEffectConstants.CLICK); + } + return showDialogInternal() || handled; + } + + @Override public boolean performLongClick() { if (super.performLongClick()) { return true; @@ -183,85 +228,9 @@ public class MediaRouteButton extends View { } cheatSheet.show(); performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - return true; } - public void setRouteTypes(int types) { - if (types == mRouteTypes) { - // Already registered; nothing to do. - return; - } - - if (mAttachedToWindow && mRouteTypes != 0) { - mRouter.removeCallback(mRouterCallback); - } - - mRouteTypes = types; - - if (mAttachedToWindow) { - updateRouteInfo(); - mRouter.addCallback(types, mRouterCallback); - } - } - - private void updateRouteInfo() { - updateRemoteIndicator(); - updateRouteCount(); - } - - public int getRouteTypes() { - return mRouteTypes; - } - - void updateRemoteIndicator() { - final RouteInfo selected = mRouter.getSelectedRoute(mRouteTypes); - final boolean isRemote = selected != mRouter.getDefaultRoute(); - final boolean isConnecting = selected != null && - selected.getStatusCode() == RouteInfo.STATUS_CONNECTING; - - boolean needsRefresh = false; - if (mRemoteActive != isRemote) { - mRemoteActive = isRemote; - needsRefresh = true; - } - if (mIsConnecting != isConnecting) { - mIsConnecting = isConnecting; - needsRefresh = true; - } - - if (needsRefresh) { - refreshDrawableState(); - } - } - - void updateRouteCount() { - final int N = mRouter.getRouteCount(); - int count = 0; - boolean hasVideoRoutes = false; - for (int i = 0; i < N; i++) { - final RouteInfo route = mRouter.getRouteAt(i); - final int routeTypes = route.getSupportedTypes(); - if ((routeTypes & mRouteTypes) != 0) { - if (route instanceof RouteGroup) { - count += ((RouteGroup) route).getRouteCount(); - } else { - count++; - } - if ((routeTypes & MediaRouter.ROUTE_TYPE_LIVE_VIDEO) != 0) { - hasVideoRoutes = true; - } - } - } - - setEnabled(count != 0); - - // Only allow toggling if we have more than just user routes. - // Don't toggle if we support video routes, we may have to let the dialog scan. - mToggleMode = count == 2 && (mRouteTypes & MediaRouter.ROUTE_TYPE_LIVE_AUDIO) != 0 && - !hasVideoRoutes; - } - @Override protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); @@ -289,6 +258,21 @@ public class MediaRouteButton extends View { } } + private void setRemoteIndicatorDrawable(Drawable d) { + if (mRemoteIndicator != null) { + mRemoteIndicator.setCallback(null); + unscheduleDrawable(mRemoteIndicator); + } + mRemoteIndicator = d; + if (d != null) { + d.setCallback(this); + d.setState(getDrawableState()); + d.setVisible(getVisibility() == VISIBLE, false); + } + + refreshDrawableState(); + } + @Override protected boolean verifyDrawable(Drawable who) { return super.verifyDrawable(who) || who == mRemoteIndicator; @@ -297,12 +281,16 @@ public class MediaRouteButton extends View { @Override public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); - if (mRemoteIndicator != null) mRemoteIndicator.jumpToCurrentState(); + + if (mRemoteIndicator != null) { + mRemoteIndicator.jumpToCurrentState(); + } } @Override public void setVisibility(int visibility) { super.setVisibility(visibility); + if (mRemoteIndicator != null) { mRemoteIndicator.setVisible(getVisibility() == VISIBLE, false); } @@ -311,19 +299,22 @@ public class MediaRouteButton extends View { @Override public void onAttachedToWindow() { super.onAttachedToWindow(); + mAttachedToWindow = true; if (mRouteTypes != 0) { - mRouter.addCallback(mRouteTypes, mRouterCallback); - updateRouteInfo(); + mRouter.addCallback(mRouteTypes, mCallback, + MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY); } + refreshRoute(); } @Override public void onDetachedFromWindow() { + mAttachedToWindow = false; if (mRouteTypes != 0) { - mRouter.removeCallback(mRouterCallback); + mRouter.removeCallback(mCallback); } - mAttachedToWindow = false; + super.onDetachedFromWindow(); } @@ -386,93 +377,71 @@ public class MediaRouteButton extends View { final int drawLeft = left + (right - left - drawWidth) / 2; final int drawTop = top + (bottom - top - drawHeight) / 2; - mRemoteIndicator.setBounds(drawLeft, drawTop, drawLeft + drawWidth, drawTop + drawHeight); + mRemoteIndicator.setBounds(drawLeft, drawTop, + drawLeft + drawWidth, drawTop + drawHeight); mRemoteIndicator.draw(canvas); } - public void setExtendedSettingsClickListener(OnClickListener listener) { - mExtendedSettingsClickListener = listener; - if (mDialogFragment != null) { - mDialogFragment.setExtendedSettingsClickListener(listener); - } - } - - /** - * Asynchronously show the route chooser dialog. - * This will attach a {@link DialogFragment} to the containing Activity. - */ - public void showDialog() { - final FragmentManager fm = getActivity().getFragmentManager(); - if (mDialogFragment == null) { - // See if one is already attached to this activity. - mDialogFragment = (MediaRouteChooserDialogFragment) fm.findFragmentByTag( - MediaRouteChooserDialogFragment.FRAGMENT_TAG); - } - if (mDialogFragment != null) { - Log.w(TAG, "showDialog(): Already showing!"); - return; - } + private void refreshRoute() { + if (mAttachedToWindow) { + final MediaRouter.RouteInfo route = mRouter.getSelectedRoute(); + final boolean isRemote = !route.isDefault() && route.matchesTypes(mRouteTypes); + final boolean isConnecting = isRemote && route.isConnecting(); + + boolean needsRefresh = false; + if (mRemoteActive != isRemote) { + mRemoteActive = isRemote; + needsRefresh = true; + } + if (mIsConnecting != isConnecting) { + mIsConnecting = isConnecting; + needsRefresh = true; + } - mDialogFragment = new MediaRouteChooserDialogFragment(); - mDialogFragment.setExtendedSettingsClickListener(mExtendedSettingsClickListener); - mDialogFragment.setLauncherListener(new MediaRouteChooserDialogFragment.LauncherListener() { - @Override - public void onDetached(MediaRouteChooserDialogFragment detachedFragment) { - mDialogFragment = null; + if (needsRefresh) { + refreshDrawableState(); } - }); - mDialogFragment.setRouteTypes(mRouteTypes); - mDialogFragment.show(fm, MediaRouteChooserDialogFragment.FRAGMENT_TAG); - } - private Activity getActivity() { - // Gross way of unwrapping the Activity so we can get the FragmentManager - Context context = getContext(); - while (context instanceof ContextWrapper && !(context instanceof Activity)) { - context = ((ContextWrapper) context).getBaseContext(); + setEnabled(mRouter.isRouteAvailable(mRouteTypes, + MediaRouter.AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE)); } - if (!(context instanceof Activity)) { - throw new IllegalStateException("The MediaRouteButton's Context is not an Activity."); - } - - return (Activity) context; } - private class MediaRouteCallback extends MediaRouter.SimpleCallback { + private final class MediaRouterCallback extends MediaRouter.SimpleCallback { @Override - public void onRouteSelected(MediaRouter router, int type, RouteInfo info) { - updateRemoteIndicator(); + public void onRouteAdded(MediaRouter router, RouteInfo info) { + refreshRoute(); } @Override - public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) { - updateRemoteIndicator(); + public void onRouteRemoved(MediaRouter router, RouteInfo info) { + refreshRoute(); } @Override public void onRouteChanged(MediaRouter router, RouteInfo info) { - updateRemoteIndicator(); + refreshRoute(); } @Override - public void onRouteAdded(MediaRouter router, RouteInfo info) { - updateRouteCount(); + public void onRouteSelected(MediaRouter router, int type, RouteInfo info) { + refreshRoute(); } @Override - public void onRouteRemoved(MediaRouter router, RouteInfo info) { - updateRouteCount(); + public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) { + refreshRoute(); } @Override public void onRouteGrouped(MediaRouter router, RouteInfo info, RouteGroup group, int index) { - updateRouteCount(); + refreshRoute(); } @Override public void onRouteUngrouped(MediaRouter router, RouteInfo info, RouteGroup group) { - updateRouteCount(); + refreshRoute(); } } } diff --git a/core/java/android/content/SyncInfo.java b/core/java/android/content/SyncInfo.java index 0284882..cffc653 100644 --- a/core/java/android/content/SyncInfo.java +++ b/core/java/android/content/SyncInfo.java @@ -55,6 +55,14 @@ public class SyncInfo implements Parcelable { } /** @hide */ + public SyncInfo(SyncInfo other) { + this.authorityId = other.authorityId; + this.account = new Account(other.account.name, other.account.type); + this.authority = other.authority; + this.startTime = other.startTime; + } + + /** @hide */ public int describeContents() { return 0; } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 267fb2a..20002ad 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -53,6 +53,7 @@ import android.content.IntentSender; * {@hide} */ interface IPackageManager { + boolean isPackageAvailable(String packageName, int userId); PackageInfo getPackageInfo(String packageName, int flags, int userId); int getPackageUid(String packageName, int userId); int[] getPackageGids(String packageName); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 17d13e5..e6da288 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -282,6 +282,10 @@ public class PackageParser { || (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0; } + public static boolean isAvailable(PackageUserState state) { + return checkUseInstalledOrBlocked(0, state); + } + public static PackageInfo generatePackageInfo(PackageParser.Package p, int gids[], int flags, long firstInstallTime, long lastUpdateTime, HashSet<String> grantedPermissions, PackageUserState state, int userId) { diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index 4fe2c4d..a38beec 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -334,6 +334,27 @@ public final class CameraCharacteristics extends CameraMetadata { /** * <p> + * If set to 1, the HAL will always split result + * metadata for a single capture into multiple buffers, + * returned using multiple process_capture_result calls. + * </p> + * <p> + * Does not need to be listed in static + * metadata. Support for partial results will be reworked in + * future versions of camera service. This quirk will stop + * working at that point; DO NOT USE without careful + * consideration of future support. + * </p> + * + * <b>Optional</b> - This value may be null on some devices. + * + * @hide + */ + public static final Key<Byte> QUIRKS_USE_PARTIAL_RESULT = + new Key<Byte>("android.quirks.usePartialResult", byte.class); + + /** + * <p> * How many output streams can be allocated at * the same time for each type of stream * </p> diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java index 7095e4d..9e8d7d1 100644 --- a/core/java/android/hardware/camera2/CameraDevice.java +++ b/core/java/android/hardware/camera2/CameraDevice.java @@ -631,6 +631,36 @@ public interface CameraDevice extends AutoCloseable { } /** + * This method is called when some results from an image capture are + * available. + * + * <p>The result provided here will contain some subset of the fields of + * a full result. Multiple onCapturePartial calls may happen per + * capture; a given result field will only be present in one partial + * capture at most. The final onCaptureCompleted call will always + * contain all the fields, whether onCapturePartial was called or + * not.</p> + * + * <p>The default implementation of this method does nothing.</p> + * + * @param camera The CameraDevice sending the callback. + * @param request The request that was given to the CameraDevice + * @param result The partial output metadata from the capture, which + * includes a subset of the CaptureResult fields. + * + * @see #capture + * @see #captureBurst + * @see #setRepeatingRequest + * @see #setRepeatingBurst + * + * @hide + */ + public void onCapturePartial(CameraDevice camera, + CaptureRequest request, CaptureResult result) { + // default empty implementation + } + + /** * This method is called when an image capture has completed and the * result metadata is available. * diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index dbd0457..535b963 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -591,6 +591,32 @@ public final class CaptureResult extends CameraMetadata { /** * <p> + * Whether a result given to the framework is the + * final one for the capture, or only a partial that contains a + * subset of the full set of dynamic metadata + * values. + * </p> + * <p> + * The entries in the result metadata buffers for a + * single capture may not overlap, except for this entry. The + * FINAL buffers must retain FIFO ordering relative to the + * requests that generate them, so the FINAL buffer for frame 3 must + * always be sent to the framework after the FINAL buffer for frame 2, and + * before the FINAL buffer for frame 4. PARTIAL buffers may be returned + * in any order relative to other frames, but all PARTIAL buffers for a given + * capture must arrive before the FINAL buffer for that capture. This entry may + * only be used by the HAL if quirks.usePartialResult is set to 1. + * </p> + * + * <b>Optional</b> - This value may be null on some devices. + * + * @hide + */ + public static final Key<Boolean> QUIRKS_PARTIAL_RESULT = + new Key<Boolean>("android.quirks.partialResult", boolean.class); + + /** + * <p> * A frame counter set by the framework. This value monotonically * increases with every new result (that is, each new result has a unique * frameCount value). diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java index c428a17..40586f0 100644 --- a/core/java/android/hardware/camera2/impl/CameraDevice.java +++ b/core/java/android/hardware/camera2/impl/CameraDevice.java @@ -279,6 +279,10 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { checkIfCameraClosed(); int requestId; + if (repeating) { + stopRepeating(); + } + try { requestId = mRemoteDevice.submitRequest(request, repeating); } catch (CameraRuntimeException e) { @@ -293,10 +297,6 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { } if (repeating) { - // Queue for deletion after in-flight requests finish - if (mRepeatingRequestId != REQUEST_ID_NONE) { - mRepeatingRequestIdDeletedList.add(mRepeatingRequestId); - } mRepeatingRequestId = requestId; } @@ -577,6 +577,9 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { } final CaptureListenerHolder holder; + Boolean quirkPartial = result.get(CaptureResult.QUIRKS_PARTIAL_RESULT); + boolean quirkIsPartialResult = (quirkPartial != null && quirkPartial); + synchronized (mLock) { // TODO: move this whole map into this class to make it more testable, // exposing the methods necessary like subscribeToRequest, unsubscribe.. @@ -585,7 +588,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { holder = CameraDevice.this.mCaptureListenerMap.get(requestId); // Clean up listener once we no longer expect to see it. - if (holder != null && !holder.isRepeating()) { + if (holder != null && !holder.isRepeating() && !quirkIsPartialResult) { CameraDevice.this.mCaptureListenerMap.remove(requestId); } @@ -595,7 +598,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { // If we received a result for a repeating request and have // prior repeating requests queued for deletion, remove those // requests from mCaptureListenerMap. - if (holder != null && holder.isRepeating() + if (holder != null && holder.isRepeating() && !quirkIsPartialResult && mRepeatingRequestIdDeletedList.size() > 0) { Iterator<Integer> iter = mRepeatingRequestIdDeletedList.iterator(); while (iter.hasNext()) { @@ -619,8 +622,25 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { final CaptureRequest request = holder.getRequest(); final CaptureResult resultAsCapture = new CaptureResult(result, request, requestId); - holder.getHandler().post( - new Runnable() { + Runnable resultDispatch = null; + + // Either send a partial result or the final capture completed result + if (quirkIsPartialResult) { + // Partial result + resultDispatch = new Runnable() { + @Override + public void run() { + if (!CameraDevice.this.isClosed()){ + holder.getListener().onCapturePartial( + CameraDevice.this, + request, + resultAsCapture); + } + } + }; + } else { + // Final capture result + resultDispatch = new Runnable() { @Override public void run() { if (!CameraDevice.this.isClosed()){ @@ -630,7 +650,10 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice { resultAsCapture); } } - }); + }; + } + + holder.getHandler().post(resultDispatch); } } diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index f12be5f..d5208d9 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -299,6 +299,10 @@ public final class DisplayManager { /** * Initiates a fresh scan of availble Wifi displays. * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast. + * <p> + * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. + * </p> + * * @hide */ public void scanWifiDisplays() { @@ -312,8 +316,7 @@ public final class DisplayManager { * Automatically remembers the display after a successful connection, if not * already remembered. * </p><p> - * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY} to connect - * to unknown displays. No permissions are required to connect to already known displays. + * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. * </p> * * @param deviceAddress The MAC address of the device to which we should connect. diff --git a/core/java/android/net/ProxyProperties.java b/core/java/android/net/ProxyProperties.java index 78ac75f..010e527 100644 --- a/core/java/android/net/ProxyProperties.java +++ b/core/java/android/net/ProxyProperties.java @@ -139,6 +139,17 @@ public class ProxyProperties implements Parcelable { return false; } + public boolean isValid() { + if (!TextUtils.isEmpty(mPacFileUrl)) return true; + try { + Proxy.validate(mHost == null ? "" : mHost, mPort == 0 ? "" : Integer.toString(mPort), + mExclusionList == null ? "" : mExclusionList); + } catch (IllegalArgumentException e) { + return false; + } + return true; + } + public java.net.Proxy makeProxy() { java.net.Proxy proxy = java.net.Proxy.NO_PROXY; if (mHost != null) { diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 7ae8ca8..9ada6e6 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -106,6 +106,11 @@ public abstract class BatteryStats implements Parcelable { public static final int FOREGROUND_ACTIVITY = 10; /** + * A constant indicating a wifi batched scan is active + */ + public static final int WIFI_BATCHED_SCAN = 11; + + /** * Include all of the data in the stats, including previously saved data. */ public static final int STATS_SINCE_CHARGED = 0; @@ -270,6 +275,8 @@ public abstract class BatteryStats implements Parcelable { public abstract void noteFullWifiLockReleasedLocked(); public abstract void noteWifiScanStartedLocked(); public abstract void noteWifiScanStoppedLocked(); + public abstract void noteWifiBatchedScanStartedLocked(int csph); + public abstract void noteWifiBatchedScanStoppedLocked(); public abstract void noteWifiMulticastEnabledLocked(); public abstract void noteWifiMulticastDisabledLocked(); public abstract void noteAudioTurnedOnLocked(); @@ -281,6 +288,7 @@ public abstract class BatteryStats implements Parcelable { public abstract long getWifiRunningTime(long batteryRealtime, int which); public abstract long getFullWifiLockTime(long batteryRealtime, int which); public abstract long getWifiScanTime(long batteryRealtime, int which); + public abstract long getWifiBatchedScanTime(int csphBin, long batteryRealtime, int which); public abstract long getWifiMulticastTime(long batteryRealtime, int which); public abstract long getAudioTurnedOnTime(long batteryRealtime, int which); @@ -288,6 +296,8 @@ public abstract class BatteryStats implements Parcelable { public abstract Timer getForegroundActivityTimer(); public abstract Timer getVibratorOnTimer(); + public static final int NUM_WIFI_BATCHED_SCAN_BINS = 5; + /** * Note that these must match the constants in android.os.PowerManager. * Also, if the user activity types change, the BatteryStatsImpl.VERSION must @@ -2081,9 +2091,11 @@ public abstract class BatteryStats implements Parcelable { TimeUtils.formatDuration(ew.usedTime, pw); pw.print(" over "); TimeUtils.formatDuration(ew.overTime, pw); - pw.print(" ("); - pw.print((ew.usedTime*100)/ew.overTime); - pw.println("%)"); + if (ew.overTime != 0) { + pw.print(" ("); + pw.print((ew.usedTime*100)/ew.overTime); + pw.println("%)"); + } } } uidActivity = true; diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java index 37a8102..f7d1eb7 100644 --- a/core/java/android/preference/Preference.java +++ b/core/java/android/preference/Preference.java @@ -1069,11 +1069,11 @@ public class Preference implements Comparable<Preference> { * @return 0 if the same; less than 0 if this Preference sorts ahead of <var>another</var>; * greater than 0 if this Preference sorts after <var>another</var>. */ + @Override public int compareTo(Preference another) { - if (mOrder != DEFAULT_ORDER - || (mOrder == DEFAULT_ORDER && another.mOrder != DEFAULT_ORDER)) { + if (mOrder != another.mOrder) { // Do order comparison - return mOrder - another.mOrder; + return mOrder - another.mOrder; } else if (mTitle == another.mTitle) { // If titles are null or share same object comparison return 0; diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java index ed9264a..7ddfa87 100644 --- a/core/java/android/preference/PreferenceActivity.java +++ b/core/java/android/preference/PreferenceActivity.java @@ -521,7 +521,9 @@ public abstract class PreferenceActivity extends ListActivity implements int initialTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0); int initialShortTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE, 0); - if (savedInstanceState != null) { + // Restore from headers only if they are supported which + // is in multi-pane mode. + if (savedInstanceState != null && !mSinglePane) { // We are restarting from a previous saved state; used that to // initialize, instead of starting fresh. ArrayList<Header> headers = savedInstanceState.getParcelableArrayList(HEADERS_TAG); @@ -573,14 +575,12 @@ public abstract class PreferenceActivity extends ListActivity implements // Single pane, showing just a prefs fragment. findViewById(com.android.internal.R.id.headers).setVisibility(View.GONE); mPrefsContainer.setVisibility(View.VISIBLE); - CharSequence initialTitleStr = null; - CharSequence initialShortTitleStr = null; if (initialTitle != 0) { - initialTitleStr = getText(initialTitle); - initialShortTitleStr = initialShortTitle != 0 + CharSequence initialTitleStr = getText(initialTitle); + CharSequence initialShortTitleStr = initialShortTitle != 0 ? getText(initialShortTitle) : null; + showBreadCrumbs(initialTitleStr, initialShortTitleStr); } - showBreadCrumbs(initialTitleStr, initialShortTitleStr); } else if (mHeaders.size() > 0) { setListAdapter(new HeaderAdapter(this, mHeaders)); if (!mSinglePane) { diff --git a/core/java/android/print/PrintDocumentAdapter.java b/core/java/android/print/PrintDocumentAdapter.java index 9e811a6..1f59bef 100644 --- a/core/java/android/print/PrintDocumentAdapter.java +++ b/core/java/android/print/PrintDocumentAdapter.java @@ -141,15 +141,36 @@ public abstract class PrintDocumentAdapter { * or {@link LayoutResultCallback#onLayoutCancelled()} if layout was * cancelled in a response to a cancellation request via the passed in * {@link CancellationSignal}. Note that you <strong>must</strong> call one of - * the methods of the given callback for this method to be considered complete. + * the methods of the given callback for this method to be considered complete + * which is you will not receive any calls to this adapter until the current + * layout operation is complete by invoking a method on the callback instance. + * The callback methods can be invoked from an arbitrary thread. * </p> * <p> + * One of the arguments passed to this method is a {@link CancellationSignal} + * which is used to propagate requests from the system to your application for + * canceling the current layout operation. For example, a cancellation may be + * requested if the user changes a print option that may affect layout while + * you are performing a layout operation. In such a case the system will make + * an attempt to cancel the current layout as another one will have to be performed. + * Typically, you should register a cancellation callback in the cancellation + * signal. The cancellation callback <strong>will not</strong> be made on the + * main thread and can be registered as follows: + * </p> + * <pre> + * cancellationSignal.setOnCancelListener(new OnCancelListener() { + * @Override + * public void onCancel() { + * // Cancel layout + * } + * }); + * </pre> + * <p> * <strong>Note:</strong> If the content is large and a layout will be * performed, it is a good practice to schedule the work on a dedicated * thread and register an observer in the provided {@link * CancellationSignal} upon invocation of which you should stop the - * layout. The cancellation callback <strong>will not</strong> be made on - * the main thread. + * layout. * </p> * * @param oldAttributes The old print attributes. @@ -177,14 +198,36 @@ public abstract class PrintDocumentAdapter { * CharSequence)}, if an error occurred; or {@link WriteResultCallback#onWriteCancelled()}, * if writing was cancelled in a response to a cancellation request via the passed * in {@link CancellationSignal}. Note that you <strong>must</strong> call one of - * the methods of the given callback for this method to be considered complete. + * the methods of the given callback for this method to be considered complete which + * is you will not receive any calls to this adapter until the current write + * operation is complete by invoking a method on the callback instance. The callback + * methods can be invoked from an arbitrary thread. + * </p> + * <p> + * One of the arguments passed to this method is a {@link CancellationSignal} + * which is used to propagate requests from the system to your application for + * canceling the current write operation. For example, a cancellation may be + * requested if the user changes a print option that may affect layout while + * you are performing a write operation. In such a case the system will make + * an attempt to cancel the current write as a layout will have to be performed + * which then may be followed by a write. Typically, you should register a + * cancellation callback in the cancellation signal. The cancellation callback + * <strong>will not</strong> be made on the main thread and can be registered + * as follows: * </p> + * <pre> + * cancellationSignal.setOnCancelListener(new OnCancelListener() { + * @Override + * public void onCancel() { + * // Cancel write + * } + * }); + * </pre> * <p> * <strong>Note:</strong> If the printed content is large, it is a good * practice to schedule writing it on a dedicated thread and register an * observer in the provided {@link CancellationSignal} upon invocation of - * which you should stop writing. The cancellation callback will not be - * made on the main thread. + * which you should stop writing. * </p> * * @param pages The pages whose content to print - non-overlapping in ascending order. diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java index d6d56bb..d1bb8fd 100644 --- a/core/java/android/print/PrintManager.java +++ b/core/java/android/print/PrintManager.java @@ -860,6 +860,11 @@ public final class PrintManager { } final ILayoutResultCallback callback; synchronized (mLock) { + if (mDestroyed) { + Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " + + "finish the printing activity before print completion?"); + return; + } callback = mCallback; clearLocked(); } @@ -876,6 +881,11 @@ public final class PrintManager { public void onLayoutFailed(CharSequence error) { final ILayoutResultCallback callback; synchronized (mLock) { + if (mDestroyed) { + Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " + + "finish the printing activity before print completion?"); + return; + } callback = mCallback; clearLocked(); } @@ -891,6 +901,11 @@ public final class PrintManager { @Override public void onLayoutCancelled() { synchronized (mLock) { + if (mDestroyed) { + Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " + + "finish the printing activity before print completion?"); + return; + } clearLocked(); } } @@ -918,6 +933,11 @@ public final class PrintManager { public void onWriteFinished(PageRange[] pages) { final IWriteResultCallback callback; synchronized (mLock) { + if (mDestroyed) { + Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " + + "finish the printing activity before print completion?"); + return; + } callback = mCallback; clearLocked(); } @@ -940,6 +960,11 @@ public final class PrintManager { public void onWriteFailed(CharSequence error) { final IWriteResultCallback callback; synchronized (mLock) { + if (mDestroyed) { + Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " + + "finish the printing activity before print completion?"); + return; + } callback = mCallback; clearLocked(); } @@ -955,6 +980,11 @@ public final class PrintManager { @Override public void onWriteCancelled() { synchronized (mLock) { + if (mDestroyed) { + Log.e(LOG_TAG, "PrintDocumentAdapter is destroyed. Did you " + + "finish the printing activity before print completion?"); + return; + } clearLocked(); } } diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java index cc81be5..49816f8 100644 --- a/core/java/android/provider/DocumentsProvider.java +++ b/core/java/android/provider/DocumentsProvider.java @@ -62,7 +62,8 @@ import java.io.FileNotFoundException; * android:authorities="com.example.mycloudprovider" * android:exported="true" * android:grantUriPermissions="true" - * android:permission="android.permission.MANAGE_DOCUMENTS"> + * android:permission="android.permission.MANAGE_DOCUMENTS" + * android:enabled="@bool/isAtLeastKitKat"> * <intent-filter> * <action android:name="android.content.action.DOCUMENTS_PROVIDER" /> * </intent-filter> @@ -252,7 +253,8 @@ public abstract class DocumentsProvider extends ContentProvider { * {@link DocumentsContract#EXTRA_LOADING} on the Cursor to indicate that * you are still fetching additional data. Then, when the network data is * available, you can send a change notification to trigger a requery and - * return the complete contents. + * return the complete contents. To return a Cursor with extras, you need to + * extend and override {@link Cursor#getExtras()}. * <p> * To support change notifications, you must * {@link Cursor#setNotificationUri(ContentResolver, Uri)} with a relevant @@ -362,7 +364,7 @@ public abstract class DocumentsProvider extends ContentProvider { * @param documentId the document to return. * @param mode the mode to open with, such as 'r', 'w', or 'rw'. * @param signal used by the caller to signal if the request should be - * cancelled. + * cancelled. May be null. * @see ParcelFileDescriptor#open(java.io.File, int, android.os.Handler, * OnCloseListener) * @see ParcelFileDescriptor#createReliablePipe() @@ -386,7 +388,7 @@ public abstract class DocumentsProvider extends ContentProvider { * @param documentId the document to return. * @param sizeHint hint of the optimal thumbnail dimensions. * @param signal used by the caller to signal if the request should be - * cancelled. + * cancelled. May be null. * @see Document#FLAG_SUPPORTS_THUMBNAIL */ @SuppressWarnings("unused") diff --git a/core/java/android/text/InputType.java b/core/java/android/text/InputType.java index 6d066d6..c596388 100644 --- a/core/java/android/text/InputType.java +++ b/core/java/android/text/InputType.java @@ -46,9 +46,9 @@ public interface InputType { * of text being given. Currently supported classes are: * {@link #TYPE_CLASS_TEXT}, {@link #TYPE_CLASS_NUMBER}, * {@link #TYPE_CLASS_PHONE}, {@link #TYPE_CLASS_DATETIME}. - * If the class is not one you + * <p>IME authors: If the class is not one you * understand, assume {@link #TYPE_CLASS_TEXT} with NO variation - * or flags. + * or flags.<p> */ public static final int TYPE_MASK_CLASS = 0x0000000f; @@ -69,7 +69,10 @@ public interface InputType { * This should be interpreted to mean that the target input connection * is not rich, it can not process and show things like candidate text nor * retrieve the current text, so the input method will need to run in a - * limited "generate key events" mode. + * limited "generate key events" mode, if it supports it. Note that some + * input methods may not support it, for example a voice-based input + * method will likely not be able to generate key events even if this + * flag is set. */ public static final int TYPE_NULL = 0x00000000; @@ -94,48 +97,70 @@ public interface InputType { * Flag for {@link #TYPE_CLASS_TEXT}: capitalize all characters. Overrides * {@link #TYPE_TEXT_FLAG_CAP_WORDS} and * {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}. This value is explicitly defined - * to be the same as {@link TextUtils#CAP_MODE_CHARACTERS}. + * to be the same as {@link TextUtils#CAP_MODE_CHARACTERS}. Of course, + * this only affects languages where there are upper-case and lower-case letters. */ public static final int TYPE_TEXT_FLAG_CAP_CHARACTERS = 0x00001000; /** - * Flag for {@link #TYPE_CLASS_TEXT}: capitalize first character of - * all words. Overrides {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}. This + * Flag for {@link #TYPE_CLASS_TEXT}: capitalize the first character of + * every word. Overrides {@link #TYPE_TEXT_FLAG_CAP_SENTENCES}. This * value is explicitly defined - * to be the same as {@link TextUtils#CAP_MODE_WORDS}. + * to be the same as {@link TextUtils#CAP_MODE_WORDS}. Of course, + * this only affects languages where there are upper-case and lower-case letters. */ public static final int TYPE_TEXT_FLAG_CAP_WORDS = 0x00002000; /** - * Flag for {@link #TYPE_CLASS_TEXT}: capitalize first character of + * Flag for {@link #TYPE_CLASS_TEXT}: capitalize the first character of * each sentence. This value is explicitly defined - * to be the same as {@link TextUtils#CAP_MODE_SENTENCES}. + * to be the same as {@link TextUtils#CAP_MODE_SENTENCES}. For example + * in English it means to capitalize after a period and a space (note that other + * languages may have different characters for period, or not use spaces, + * or use different grammatical rules). Of course, + * this only affects languages where there are upper-case and lower-case letters. */ public static final int TYPE_TEXT_FLAG_CAP_SENTENCES = 0x00004000; /** * Flag for {@link #TYPE_CLASS_TEXT}: the user is entering free-form - * text that should have auto-correction applied to it. + * text that should have auto-correction applied to it. Without this flag, + * the IME will not try to correct typos. You should always set this flag + * unless you really expect users to type non-words in this field, for + * example to choose a name for a character in a game. + * Contrast this with {@link #TYPE_TEXT_FLAG_AUTO_COMPLETE} and + * {@link #TYPE_TEXT_FLAG_NO_SUGGESTIONS}: + * {@code TYPE_TEXT_FLAG_AUTO_CORRECT} means that the IME will try to + * auto-correct typos as the user is typing, but does not define whether + * the IME offers an interface to show suggestions. */ public static final int TYPE_TEXT_FLAG_AUTO_CORRECT = 0x00008000; /** - * Flag for {@link #TYPE_CLASS_TEXT}: the text editor is performing - * auto-completion of the text being entered based on its own semantics, - * which it will present to the user as they type. This generally means - * that the input method should not be showing candidates itself, but can - * expect for the editor to supply its own completions/candidates from + * Flag for {@link #TYPE_CLASS_TEXT}: the text editor (which means + * the application) is performing auto-completion of the text being entered + * based on its own semantics, which it will present to the user as they type. + * This generally means that the input method should not be showing + * candidates itself, but can expect the editor to supply its own + * completions/candidates from * {@link android.view.inputmethod.InputMethodSession#displayCompletions * InputMethodSession.displayCompletions()} as a result of the editor calling * {@link android.view.inputmethod.InputMethodManager#displayCompletions * InputMethodManager.displayCompletions()}. + * Note the contrast with {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} and + * {@link #TYPE_TEXT_FLAG_NO_SUGGESTIONS}: + * {@code TYPE_TEXT_FLAG_AUTO_COMPLETE} means the editor should show an + * interface for displaying suggestions, but instead of supplying its own + * it will rely on the Editor to pass completions/corrections. */ public static final int TYPE_TEXT_FLAG_AUTO_COMPLETE = 0x00010000; /** * Flag for {@link #TYPE_CLASS_TEXT}: multiple lines of text can be * entered into the field. If this flag is not set, the text field - * will be constrained to a single line. + * will be constrained to a single line. The IME may also choose not to + * display an enter key when this flag is not set, as there should be no + * need to create new lines. */ public static final int TYPE_TEXT_FLAG_MULTI_LINE = 0x00020000; @@ -152,6 +177,16 @@ public interface InputType { * do not contain words from the language and do not benefit from any * dictionary-based completions or corrections. It overrides the * {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} value when set. + * Please avoid using this unless you are certain this is what you want. + * Many input methods need suggestions to work well, for example the ones + * based on gesture typing. Consider clearing + * {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} instead if you just do not + * want the IME to correct typos. + * Note the contrast with {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} and + * {@link #TYPE_TEXT_FLAG_AUTO_COMPLETE}: + * {@code TYPE_TEXT_FLAG_NO_SUGGESTIONS} means the IME should never + * show an interface to display suggestions. Most IMEs will also take this to + * mean they should not try to auto-correct what the user is typing. */ public static final int TYPE_TEXT_FLAG_NO_SUGGESTIONS = 0x00080000; @@ -224,7 +259,9 @@ public interface InputType { /** * Variation of {@link #TYPE_CLASS_TEXT}: entering text for phonetic - * pronunciation, such as a phonetic name field in contacts. + * pronunciation, such as a phonetic name field in contacts. This is mostly + * useful for languages where one spelling may have several phonetic + * readings, like Japanese. */ public static final int TYPE_TEXT_VARIATION_PHONETIC = 0x000000c0; @@ -255,12 +292,13 @@ public interface InputType { // ---------------------------------------------------------------------- /** - * Class for numeric text. This class supports the following flag: + * Class for numeric text. This class supports the following flags: * {@link #TYPE_NUMBER_FLAG_SIGNED} and * {@link #TYPE_NUMBER_FLAG_DECIMAL}. It also supports the following * variations: {@link #TYPE_NUMBER_VARIATION_NORMAL} and - * {@link #TYPE_NUMBER_VARIATION_PASSWORD}. If you do not recognize - * the variation, normal should be assumed. + * {@link #TYPE_NUMBER_VARIATION_PASSWORD}. + * <p>IME authors: If you do not recognize + * the variation, normal should be assumed.</p> */ public static final int TYPE_CLASS_NUMBER = 0x00000002; @@ -318,7 +356,7 @@ public interface InputType { * following variations: * {@link #TYPE_DATETIME_VARIATION_NORMAL} * {@link #TYPE_DATETIME_VARIATION_DATE}, and - * {@link #TYPE_DATETIME_VARIATION_TIME},. + * {@link #TYPE_DATETIME_VARIATION_TIME}. */ public static final int TYPE_CLASS_DATETIME = 0x00000004; diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 354ea66..7d310a2 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -643,6 +643,15 @@ public final class Display { || uid == 0; } + /** + * Returns true if the display is a public presentation display. + * @hide + */ + public boolean isPublicPresentation() { + return (mFlags & (Display.FLAG_PRIVATE | Display.FLAG_PRESENTATION)) == + Display.FLAG_PRESENTATION; + } + private void updateDisplayInfoLocked() { // Note: The display manager caches display info objects on our behalf. DisplayInfo newInfo = mGlobal.getDisplayInfo(mDisplayId); diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 1b76cb1..c92a104 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -78,7 +78,8 @@ interface IWindowManager void addWindowToken(IBinder token, int type); void removeWindowToken(IBinder token); void addAppToken(int addPos, IApplicationToken token, int groupId, int stackId, - int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId); + int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId, + int configChanges); void setAppGroupId(IBinder token, int groupId); void setAppOrientation(IApplicationToken token, int requestedOrientation); int getAppOrientation(IApplicationToken token); diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java index f36c78f..42a58a8 100644 --- a/core/java/android/view/ScaleGestureDetector.java +++ b/core/java/android/view/ScaleGestureDetector.java @@ -323,6 +323,10 @@ public class ScaleGestureDetector { mInProgress = false; mInitialSpan = 0; mDoubleTapMode = DOUBLE_TAP_MODE_NONE; + } else if (mDoubleTapMode == DOUBLE_TAP_MODE_IN_PROGRESS && streamComplete) { + mInProgress = false; + mInitialSpan = 0; + mDoubleTapMode = DOUBLE_TAP_MODE_NONE; } if (streamComplete) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index aa2b0d4..06f8e8c 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -18,7 +18,6 @@ package android.view; import android.content.ClipData; import android.content.Context; -import android.content.pm.ApplicationInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; @@ -3102,7 +3101,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ private static final int UNDEFINED_PADDING = Integer.MIN_VALUE; - private boolean mUseBackgroundPadding = false; + /** + * Cache if a left padding has been defined + */ + private boolean mLeftPaddingDefined = false; + + /** + * Cache if a right padding has been defined + */ + private boolean mRightPaddingDefined = false; /** * @hide @@ -3532,10 +3539,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int overScrollMode = mOverScrollMode; boolean initializeScrollbars = false; - boolean leftPaddingDefined = false; - boolean rightPaddingDefined = false; boolean startPaddingDefined = false; boolean endPaddingDefined = false; + boolean leftPaddingDefined = false; + boolean rightPaddingDefined = false; final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; @@ -3867,6 +3874,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setBackground(background); } + // setBackground above will record that padding is currently provided by the background. + // If we have padding specified via xml, record that here instead and use it. + mLeftPaddingDefined = leftPaddingDefined; + mRightPaddingDefined = rightPaddingDefined; + if (padding >= 0) { leftPadding = padding; topPadding = padding; @@ -3884,11 +3896,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if // defined. - if (!leftPaddingDefined && startPaddingDefined) { + if (!mLeftPaddingDefined && startPaddingDefined) { leftPadding = startPadding; } mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial; - if (!rightPaddingDefined && endPaddingDefined) { + if (!mRightPaddingDefined && endPaddingDefined) { rightPadding = endPadding; } mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial; @@ -3900,10 +3912,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // defined. final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined; - if (leftPaddingDefined && !hasRelativePadding) { + if (mLeftPaddingDefined && !hasRelativePadding) { mUserPaddingLeftInitial = leftPadding; } - if (rightPaddingDefined && !hasRelativePadding) { + if (mRightPaddingDefined && !hasRelativePadding) { mUserPaddingRightInitial = rightPadding; } } @@ -12347,15 +12359,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback, // If start / end padding are defined, they will be resolved (hence overriding) to // left / right or right / left depending on the resolved layout direction. // If start / end padding are not defined, use the left / right ones. - if (mBackground != null && mUseBackgroundPadding) { + if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) { Rect padding = sThreadLocal.get(); if (padding == null) { padding = new Rect(); sThreadLocal.set(padding); } mBackground.getPadding(padding); - mUserPaddingLeftInitial = padding.left; - mUserPaddingRightInitial = padding.right; + if (!mLeftPaddingDefined) { + mUserPaddingLeftInitial = padding.left; + } + if (!mRightPaddingDefined) { + mUserPaddingRightInitial = padding.right; + } } switch (resolvedLayoutDirection) { case LAYOUT_DIRECTION_RTL: @@ -15352,9 +15368,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mUserPaddingRightInitial = padding.right; internalSetPadding(padding.left, padding.top, padding.right, padding.bottom); } - mUseBackgroundPadding = true; - } else { - mUseBackgroundPadding = false; + mLeftPaddingDefined = false; + mRightPaddingDefined = false; } // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or @@ -15380,8 +15395,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /* Remove the background */ mBackground = null; - mUseBackgroundPadding = false; - if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) { /* * This view ONLY drew the background before and we're removing @@ -15453,7 +15466,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mUserPaddingLeftInitial = left; mUserPaddingRightInitial = right; - mUseBackgroundPadding = false; + mLeftPaddingDefined = true; + mRightPaddingDefined = true; internalSetPadding(left, top, right, bottom); } @@ -15540,8 +15554,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mUserPaddingStart = start; mUserPaddingEnd = end; - - mUseBackgroundPadding = false; + mLeftPaddingDefined = true; + mRightPaddingDefined = true; switch(getLayoutDirection()) { case LAYOUT_DIRECTION_RTL: diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java index 5146567..d4e005b 100644 --- a/core/java/android/view/inputmethod/EditorInfo.java +++ b/core/java/android/view/inputmethod/EditorInfo.java @@ -70,14 +70,14 @@ public class EditorInfo implements InputType, Parcelable { /** * Bits of {@link #IME_MASK_ACTION}: the action key performs a "search" * operation, taking the user to the results of searching for the text - * the have typed (in whatever context is appropriate). + * they have typed (in whatever context is appropriate). */ public static final int IME_ACTION_SEARCH = 0x00000003; /** * Bits of {@link #IME_MASK_ACTION}: the action key performs a "send" * operation, delivering the text to its target. This is typically used - * when composing a message. + * when composing a message in IM or SMS where sending is immediate. */ public static final int IME_ACTION_SEND = 0x00000004; @@ -89,22 +89,31 @@ public class EditorInfo implements InputType, Parcelable { /** * Bits of {@link #IME_MASK_ACTION}: the action key performs a "done" - * operation, typically meaning the IME will be closed. + * operation, typically meaning there is nothing more to input and the + * IME will be closed. */ public static final int IME_ACTION_DONE = 0x00000006; /** * Bits of {@link #IME_MASK_ACTION}: Like {@link #IME_ACTION_NEXT}, but * for moving to the previous field. This will normally not be used to - * specify an action (since it precludes {@link #IME_ACTION_NEXT}, but + * specify an action (since it precludes {@link #IME_ACTION_NEXT}), but * can be returned to the app if it sets {@link #IME_FLAG_NAVIGATE_PREVIOUS}. */ public static final int IME_ACTION_PREVIOUS = 0x00000007; /** * Flag of {@link #imeOptions}: used to request that the IME never go - * into fullscreen mode. Applications need to be aware that the flag is not - * a guarantee, and not all IMEs will respect it. + * into fullscreen mode. + * By default, IMEs may go into full screen mode when they think + * it's appropriate, for example on small screens in landscape + * orientation where displaying a software keyboard may occlude + * such a large portion of the screen that the remaining part is + * too small to meaningfully display the application UI. + * If this flag is set, compliant IMEs will never go into full screen mode, + * and always leave some space to display the application UI. + * Applications need to be aware that the flag is not a guarantee, and + * some IMEs may ignore it. */ public static final int IME_FLAG_NO_FULLSCREEN = 0x2000000; @@ -136,50 +145,56 @@ public class EditorInfo implements InputType, Parcelable { * Flag of {@link #imeOptions}: used to specify that the IME does not need * to show its extracted text UI. For input methods that may be fullscreen, * often when in landscape mode, this allows them to be smaller and let part - * of the application be shown behind. Though there will likely be limited - * access to the application available from the user, it can make the - * experience of a (mostly) fullscreen IME less jarring. Note that when - * this flag is specified the IME may <em>not</em> be set up to be able - * to display text, so it should only be used in situations where this is - * not needed. + * of the application be shown behind, through transparent UI parts in the + * fullscreen IME. The part of the UI visible to the user may not be responsive + * to touch because the IME will receive touch events, which may confuse the + * user; use {@link #IME_FLAG_NO_FULLSCREEN} instead for a better experience. + * Using this flag is discouraged and it may become deprecated in the future. + * Its meaning is unclear in some situations and it may not work appropriately + * on older versions of the platform. */ public static final int IME_FLAG_NO_EXTRACT_UI = 0x10000000; /** - * Flag of {@link #imeOptions}: used in conjunction with - * {@link #IME_MASK_ACTION}, this indicates that the action should not - * be available as an accessory button when the input method is full-screen. - * Note that by setting this flag, there can be cases where the action - * is simply never available to the user. Setting this generally means - * that you think showing text being edited is more important than the - * action you have supplied. + * Flag of {@link #imeOptions}: used in conjunction with one of the actions + * masked by {@link #IME_MASK_ACTION}, this indicates that the action + * should not be available as an accessory button on the right of the extracted + * text when the input method is full-screen. Note that by setting this flag, + * there can be cases where the action is simply never available to the + * user. Setting this generally means that you think that in fullscreen mode, + * where there is little space to show the text, it's not worth taking some + * screen real estate to display the action and it should be used instead + * to show more text. */ public static final int IME_FLAG_NO_ACCESSORY_ACTION = 0x20000000; /** - * Flag of {@link #imeOptions}: used in conjunction with - * {@link #IME_MASK_ACTION}, this indicates that the action should not - * be available in-line as a replacement for "enter" key. Typically this is - * because the action has such a significant impact or is not recoverable - * enough that accidentally hitting it should be avoided, such as sending - * a message. Note that {@link android.widget.TextView} will automatically set this - * flag for you on multi-line text views. + * Flag of {@link #imeOptions}: used in conjunction with one of the actions + * masked by {@link #IME_MASK_ACTION}. If this flag is not set, IMEs will + * normally replace the "enter" key with the action supplied. This flag + * indicates that the action should not be available in-line as a replacement + * for the "enter" key. Typically this is because the action has such a + * significant impact or is not recoverable enough that accidentally hitting + * it should be avoided, such as sending a message. Note that + * {@link android.widget.TextView} will automatically set this flag for you + * on multi-line text views. */ public static final int IME_FLAG_NO_ENTER_ACTION = 0x40000000; /** - * Flag of {@link #imeOptions}: used to request that the IME is capable of + * Flag of {@link #imeOptions}: used to request an IME that is capable of * inputting ASCII characters. The intention of this flag is to ensure that - * the user can type Roman alphabet characters in a {@link android.widget.TextView} - * used for, typically, account ID or password input. It is expected that IMEs - * normally are able to input ASCII even without being told so (such IMEs - * already respect this flag in a sense), but there could be some cases they - * aren't when, for instance, only non-ASCII input languagaes like Arabic, - * Greek, Hebrew, Russian are enabled in the IME. Applications need to be - * aware that the flag is not a guarantee, and not all IMEs will respect it. + * the user can type Roman alphabet characters in a {@link android.widget.TextView}. + * It is typically used for an account ID or password input. A lot of the time, + * IMEs are already able to input ASCII even without being told so (such IMEs + * already respect this flag in a sense), but there are cases when this is not + * the default. For instance, users of languages using a different script like + * Arabic, Greek, Hebrew or Russian typically have a keyboard that can't + * input ASCII characters by default. Applications need to be + * aware that the flag is not a guarantee, and some IMEs may not respect it. * However, it is strongly recommended for IME authors to respect this flag - * especially when their IME could end up with a state that has only non-ASCII - * input languages enabled. + * especially when their IME could end up with a state where only languages + * using non-ASCII are enabled. */ public static final int IME_FLAG_FORCE_ASCII = 0x80000000; @@ -209,8 +224,13 @@ public class EditorInfo implements InputType, Parcelable { /** * In some cases an IME may be able to display an arbitrary label for - * a command the user can perform, which you can specify here. You can - * not count on this being used. + * a command the user can perform, which you can specify here. This is + * typically used as the label for the action to use in-line as a replacement + * for the "enter" key (see {@link #actionId}). Remember the key where + * this will be displayed is typically very small, and there are significant + * localization challenges to make this fit in all supported languages. Also + * you can not count absolutely on this being used, as some IMEs may + * ignore this. */ public CharSequence actionLabel = null; @@ -224,13 +244,17 @@ public class EditorInfo implements InputType, Parcelable { /** * The text offset of the start of the selection at the time editing - * began; -1 if not known. + * began; -1 if not known. Keep in mind some IMEs may not be able + * to give their full feature set without knowing the cursor position; + * avoid passing -1 here if you can. */ public int initialSelStart = -1; /** * The text offset of the end of the selection at the time editing - * began; -1 if not known. + * began; -1 if not known. Keep in mind some IMEs may not be able + * to give their full feature set without knowing the cursor position; + * avoid passing -1 here if you can. */ public int initialSelEnd = -1; @@ -280,7 +304,7 @@ public class EditorInfo implements InputType, Parcelable { * Any extra data to supply to the input method. This is for extended * communication with specific input methods; the name fields in the * bundle should be scoped (such as "com.mydomain.im.SOME_FIELD") so - * that they don't conflict with others. This field is can be + * that they don't conflict with others. This field can be * filled in from the {@link android.R.attr#editorExtras} * attribute of a TextView. */ diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java index 59330ca..3537aec 100644 --- a/core/java/android/view/inputmethod/InputConnection.java +++ b/core/java/android/view/inputmethod/InputConnection.java @@ -142,7 +142,11 @@ public interface InputConnection { * conditions in implementing this call. An IME can make a change * to the text and use this method right away; you need to make * sure the returned value is consistent with the result of the - * latest edits. + * latest edits. Also, you may return less than n characters if performance + * dictates so, but keep in mind IMEs are relying on this for many + * functions: you should not, for example, limit the returned value to + * the current line, and specifically do not return 0 characters unless + * the cursor is really at the start of the text.</p> * * @param n The expected length of the text. * @param flags Supplies additional options controlling how the text is @@ -176,7 +180,11 @@ public interface InputConnection { * conditions in implementing this call. An IME can make a change * to the text and use this method right away; you need to make * sure the returned value is consistent with the result of the - * latest edits.</p> + * latest edits. Also, you may return less than n characters if performance + * dictates so, but keep in mind IMEs are relying on this for many + * functions: you should not, for example, limit the returned value to + * the current line, and specifically do not return 0 characters unless + * the cursor is really at the end of the text.</p> * * @param n The expected length of the text. * @param flags Supplies additional options controlling how the text is diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java index 40f95ce..2ab3024 100644 --- a/core/java/android/view/inputmethod/InputMethodSubtype.java +++ b/core/java/android/view/inputmethod/InputMethodSubtype.java @@ -534,6 +534,13 @@ public final class InputMethodSubtype implements Parcelable { private static int hashCodeInternal(String locale, String mode, String extraValue, boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype, boolean isAsciiCapable) { + // CAVEAT: Must revisit how to compute needsToCalculateCompatibleHashCode when a new + // attribute is added in order to avoid enabled subtypes being unexpectedly disabled. + final boolean needsToCalculateCompatibleHashCode = !isAsciiCapable; + if (needsToCalculateCompatibleHashCode) { + return Arrays.hashCode(new Object[] {locale, mode, extraValue, isAuxiliary, + overridesImplicitlyEnabledSubtype}); + } return Arrays.hashCode(new Object[] {locale, mode, extraValue, isAuxiliary, overridesImplicitlyEnabledSubtype, isAsciiCapable}); } diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java index 9e35a23..7daf798 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -710,6 +710,7 @@ public class ImageView extends View { } d.setLevel(mLevel); d.setLayoutDirection(getLayoutDirection()); + d.setVisible(getVisibility() == VISIBLE, true); mDrawableWidth = d.getIntrinsicWidth(); mDrawableHeight = d.getIntrinsicHeight(); applyColorMod(); diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java index fbdf318..d57b739 100644 --- a/core/java/android/widget/VideoView.java +++ b/core/java/android/widget/VideoView.java @@ -56,7 +56,17 @@ import java.util.Vector; * can load images from various sources (such as resources or content * providers), takes care of computing its measurement from the video so that * it can be used in any layout manager, and provides various display options - * such as scaling and tinting. + * such as scaling and tinting.<p> + * + * <em>Note: VideoView does not retain its full state when going into the + * background.</em> In particular, it does not restore the current play state, + * play position, selected tracks, or any subtitle tracks added via + * {@link #addSubtitleSource addSubtitleSource()}. Applications should + * save and restore these on their own in + * {@link android.app.Activity#onSaveInstanceState} and + * {@link android.app.Activity#onRestoreInstanceState}.<p> + * Also note that the audio session id (from {@link #getAudioSessionId}) may + * change from its previously returned value when the VideoView is restored. */ public class VideoView extends SurfaceView implements MediaPlayerControl, SubtitleController.Anchor { diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index 525517c..43c4b49 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -68,6 +68,8 @@ interface IBatteryStats { void noteFullWifiLockReleasedFromSource(in WorkSource ws); void noteWifiScanStartedFromSource(in WorkSource ws); void noteWifiScanStoppedFromSource(in WorkSource ws); + void noteWifiBatchedScanStartedFromSource(in WorkSource ws, int csph); + void noteWifiBatchedScanStoppedFromSource(in WorkSource ws); void noteWifiMulticastEnabledFromSource(in WorkSource ws); void noteWifiMulticastDisabledFromSource(in WorkSource ws); void noteNetworkInterfaceType(String iface, int type); diff --git a/core/java/com/android/internal/app/MediaRouteChooserDialog.java b/core/java/com/android/internal/app/MediaRouteChooserDialog.java new file mode 100644 index 0000000..47d2a9c --- /dev/null +++ b/core/java/com/android/internal/app/MediaRouteChooserDialog.java @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.app; + +import com.android.internal.R; + +import android.app.Dialog; +import android.content.Context; +import android.media.MediaRouter; +import android.media.MediaRouter.RouteInfo; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ListView; +import android.widget.TextView; + +import java.util.Comparator; + +/** + * This class implements the route chooser dialog for {@link MediaRouter}. + * <p> + * This dialog allows the user to choose a route that matches a given selector. + * </p> + * + * @see MediaRouteButton + * @see MediaRouteActionProvider + * + * TODO: Move this back into the API, as in the support library media router. + */ +public class MediaRouteChooserDialog extends Dialog { + private final MediaRouter mRouter; + private final MediaRouterCallback mCallback; + + private int mRouteTypes; + private View.OnClickListener mExtendedSettingsClickListener; + private RouteAdapter mAdapter; + private ListView mListView; + private Button mExtendedSettingsButton; + private boolean mAttachedToWindow; + + public MediaRouteChooserDialog(Context context, int theme) { + super(context, theme); + + mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE); + mCallback = new MediaRouterCallback(); + } + + /** + * Gets the media route types for filtering the routes that the user can + * select using the media route chooser dialog. + * + * @return The route types. + */ + public int getRouteTypes() { + return mRouteTypes; + } + + /** + * Sets the types of routes that will be shown in the media route chooser dialog + * launched by this button. + * + * @param types The route types to match. + */ + public void setRouteTypes(int types) { + if (mRouteTypes != types) { + mRouteTypes = types; + + if (mAttachedToWindow) { + mRouter.removeCallback(mCallback); + mRouter.addCallback(types, mCallback, + MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN); + } + + refreshRoutes(); + } + } + + public void setExtendedSettingsClickListener(View.OnClickListener listener) { + if (listener != mExtendedSettingsClickListener) { + mExtendedSettingsClickListener = listener; + updateExtendedSettingsButton(); + } + } + + /** + * Returns true if the route should be included in the list. + * <p> + * The default implementation returns true for enabled non-default routes that + * match the route types. Subclasses can override this method to filter routes + * differently. + * </p> + * + * @param route The route to consider, never null. + * @return True if the route should be included in the chooser dialog. + */ + public boolean onFilterRoute(MediaRouter.RouteInfo route) { + return !route.isDefault() && route.isEnabled() && route.matchesTypes(mRouteTypes); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + getWindow().requestFeature(Window.FEATURE_LEFT_ICON); + + setContentView(R.layout.media_route_chooser_dialog); + setTitle(mRouteTypes == MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY + ? R.string.media_route_chooser_title_for_remote_display + : R.string.media_route_chooser_title); + + // Must be called after setContentView. + getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, + R.drawable.ic_media_route_off_holo_dark); + + mAdapter = new RouteAdapter(getContext()); + mListView = (ListView)findViewById(R.id.media_route_list); + mListView.setAdapter(mAdapter); + mListView.setOnItemClickListener(mAdapter); + mListView.setEmptyView(findViewById(android.R.id.empty)); + + mExtendedSettingsButton = (Button)findViewById(R.id.media_route_extended_settings_button); + updateExtendedSettingsButton(); + } + + private void updateExtendedSettingsButton() { + if (mExtendedSettingsButton != null) { + mExtendedSettingsButton.setOnClickListener(mExtendedSettingsClickListener); + mExtendedSettingsButton.setVisibility( + mExtendedSettingsClickListener != null ? View.VISIBLE : View.GONE); + } + } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + + mAttachedToWindow = true; + mRouter.addCallback(mRouteTypes, mCallback, MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN); + refreshRoutes(); + } + + @Override + public void onDetachedFromWindow() { + mAttachedToWindow = false; + mRouter.removeCallback(mCallback); + + super.onDetachedFromWindow(); + } + + /** + * Refreshes the list of routes that are shown in the chooser dialog. + */ + public void refreshRoutes() { + if (mAttachedToWindow) { + mAdapter.update(); + } + } + + private final class RouteAdapter extends ArrayAdapter<MediaRouter.RouteInfo> + implements ListView.OnItemClickListener { + private final LayoutInflater mInflater; + + public RouteAdapter(Context context) { + super(context, 0); + mInflater = LayoutInflater.from(context); + } + + public void update() { + clear(); + final int count = mRouter.getRouteCount(); + for (int i = 0; i < count; i++) { + MediaRouter.RouteInfo route = mRouter.getRouteAt(i); + if (onFilterRoute(route)) { + add(route); + } + } + sort(RouteComparator.sInstance); + notifyDataSetChanged(); + } + + @Override + public boolean areAllItemsEnabled() { + return false; + } + + @Override + public boolean isEnabled(int position) { + return getItem(position).isEnabled(); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View view = convertView; + if (view == null) { + view = mInflater.inflate(R.layout.media_route_list_item, parent, false); + } + MediaRouter.RouteInfo route = getItem(position); + TextView text1 = (TextView)view.findViewById(android.R.id.text1); + TextView text2 = (TextView)view.findViewById(android.R.id.text2); + text1.setText(route.getName()); + CharSequence description = route.getDescription(); + if (TextUtils.isEmpty(description)) { + text2.setVisibility(View.GONE); + text2.setText(""); + } else { + text2.setVisibility(View.VISIBLE); + text2.setText(description); + } + view.setEnabled(route.isEnabled()); + return view; + } + + @Override + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + MediaRouter.RouteInfo route = getItem(position); + if (route.isEnabled()) { + route.select(); + dismiss(); + } + } + } + + private final class MediaRouterCallback extends MediaRouter.SimpleCallback { + @Override + public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo info) { + refreshRoutes(); + } + + @Override + public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo info) { + refreshRoutes(); + } + + @Override + public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo info) { + refreshRoutes(); + } + + @Override + public void onRouteSelected(MediaRouter router, int type, RouteInfo info) { + dismiss(); + } + } + + private static final class RouteComparator implements Comparator<MediaRouter.RouteInfo> { + public static final RouteComparator sInstance = new RouteComparator(); + + @Override + public int compare(MediaRouter.RouteInfo lhs, MediaRouter.RouteInfo rhs) { + return lhs.getName().toString().compareTo(rhs.getName().toString()); + } + } +} diff --git a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java index e300021..ae362af 100644 --- a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java +++ b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 The Android Open Source Project + * Copyright (C) 2013 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. @@ -16,675 +16,86 @@ package com.android.internal.app; -import com.android.internal.R; - -import android.app.Activity; import android.app.Dialog; import android.app.DialogFragment; -import android.app.MediaRouteActionProvider; -import android.app.MediaRouteButton; import android.content.Context; -import android.graphics.drawable.Drawable; -import android.hardware.display.DisplayManager; -import android.media.MediaRouter; -import android.media.MediaRouter.RouteCategory; -import android.media.MediaRouter.RouteGroup; -import android.media.MediaRouter.RouteInfo; import android.os.Bundle; -import android.text.TextUtils; -import android.view.KeyEvent; -import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.BaseAdapter; -import android.widget.CheckBox; -import android.widget.Checkable; -import android.widget.ImageButton; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.SeekBar; -import android.widget.TextView; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; +import android.view.View.OnClickListener; /** - * This class implements the route chooser dialog for {@link MediaRouter}. + * Media route chooser dialog fragment. + * <p> + * Creates a {@link MediaRouteChooserDialog}. The application may subclass + * this dialog fragment to customize the media route chooser dialog. + * </p> * - * @see MediaRouteButton - * @see MediaRouteActionProvider + * TODO: Move this back into the API, as in the support library media router. */ public class MediaRouteChooserDialogFragment extends DialogFragment { - private static final String TAG = "MediaRouteChooserDialogFragment"; - public static final String FRAGMENT_TAG = "android:MediaRouteChooserDialogFragment"; - - private static final int[] ITEM_LAYOUTS = new int[] { - R.layout.media_route_list_item_top_header, - R.layout.media_route_list_item_section_header, - R.layout.media_route_list_item, - R.layout.media_route_list_item_checkable, - R.layout.media_route_list_item_collapse_group - }; + private final String ARGUMENT_ROUTE_TYPES = "routeTypes"; - MediaRouter mRouter; - private int mRouteTypes; - - private LayoutInflater mInflater; - private LauncherListener mLauncherListener; - private View.OnClickListener mExtendedSettingsListener; - private RouteAdapter mAdapter; - private ListView mListView; - private SeekBar mVolumeSlider; - private ImageView mVolumeIcon; - - final RouteComparator mComparator = new RouteComparator(); - final MediaRouterCallback mCallback = new MediaRouterCallback(); - private boolean mIgnoreSliderVolumeChanges; - private boolean mIgnoreCallbackVolumeChanges; + private View.OnClickListener mExtendedSettingsClickListener; + /** + * Creates a media route chooser dialog fragment. + * <p> + * All subclasses of this class must also possess a default constructor. + * </p> + */ public MediaRouteChooserDialogFragment() { - setStyle(STYLE_NO_TITLE, R.style.Theme_DeviceDefault_Dialog); + setCancelable(true); + setStyle(STYLE_NORMAL, android.R.style.Theme_DeviceDefault_Dialog); } - public void setLauncherListener(LauncherListener listener) { - mLauncherListener = listener; - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - mRouter = (MediaRouter) activity.getSystemService(Context.MEDIA_ROUTER_SERVICE); - mRouter.addCallback(mRouteTypes, mCallback, MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN); - } - - @Override - public void onDetach() { - super.onDetach(); - if (mLauncherListener != null) { - mLauncherListener.onDetached(this); - } - if (mAdapter != null) { - mAdapter = null; - } - mInflater = null; - mRouter.removeCallback(mCallback); - mRouter = null; - } - - public void setExtendedSettingsClickListener(View.OnClickListener listener) { - mExtendedSettingsListener = listener; + public int getRouteTypes() { + Bundle args = getArguments(); + return args != null ? args.getInt(ARGUMENT_ROUTE_TYPES) : 0; } public void setRouteTypes(int types) { - mRouteTypes = types; - } - - void updateVolume() { - if (mRouter == null) return; - - final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes); - mVolumeIcon.setImageResource(selectedRoute == null || - selectedRoute.getPlaybackType() == RouteInfo.PLAYBACK_TYPE_LOCAL ? - R.drawable.ic_audio_vol : R.drawable.ic_media_route_on_holo_dark); - - mIgnoreSliderVolumeChanges = true; - - if (selectedRoute == null || - selectedRoute.getVolumeHandling() == RouteInfo.PLAYBACK_VOLUME_FIXED) { - // Disable the slider and show it at max volume. - mVolumeSlider.setMax(1); - mVolumeSlider.setProgress(1); - mVolumeSlider.setEnabled(false); - } else { - mVolumeSlider.setEnabled(true); - mVolumeSlider.setMax(selectedRoute.getVolumeMax()); - mVolumeSlider.setProgress(selectedRoute.getVolume()); - } - - mIgnoreSliderVolumeChanges = false; - } - - void changeVolume(int newValue) { - if (mIgnoreSliderVolumeChanges) return; - - final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes); - if (selectedRoute != null && - selectedRoute.getVolumeHandling() == RouteInfo.PLAYBACK_VOLUME_VARIABLE) { - final int maxVolume = selectedRoute.getVolumeMax(); - newValue = Math.max(0, Math.min(newValue, maxVolume)); - selectedRoute.requestSetVolume(newValue); - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - mInflater = inflater; - final View layout = inflater.inflate(R.layout.media_route_chooser_layout, container, false); - - mVolumeIcon = (ImageView) layout.findViewById(R.id.volume_icon); - mVolumeSlider = (SeekBar) layout.findViewById(R.id.volume_slider); - updateVolume(); - mVolumeSlider.setOnSeekBarChangeListener(new VolumeSliderChangeListener()); - - if (mExtendedSettingsListener != null) { - final View extendedSettingsButton = layout.findViewById(R.id.extended_settings); - extendedSettingsButton.setVisibility(View.VISIBLE); - extendedSettingsButton.setOnClickListener(mExtendedSettingsListener); - } - - final ListView list = (ListView) layout.findViewById(R.id.list); - list.setItemsCanFocus(true); - list.setAdapter(mAdapter = new RouteAdapter()); - list.setOnItemClickListener(mAdapter); - - mListView = list; - - mAdapter.scrollToSelectedItem(); - - return layout; - } - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - return new RouteChooserDialog(getActivity(), getTheme()); - } - - private static class ViewHolder { - public TextView text1; - public TextView text2; - public ImageView icon; - public ImageButton expandGroupButton; - public RouteAdapter.ExpandGroupListener expandGroupListener; - public int position; - public CheckBox check; - } - - private class RouteAdapter extends BaseAdapter implements ListView.OnItemClickListener { - private static final int VIEW_TOP_HEADER = 0; - private static final int VIEW_SECTION_HEADER = 1; - private static final int VIEW_ROUTE = 2; - private static final int VIEW_GROUPING_ROUTE = 3; - private static final int VIEW_GROUPING_DONE = 4; - - private int mSelectedItemPosition = -1; - private final ArrayList<Object> mItems = new ArrayList<Object>(); - - private RouteCategory mCategoryEditingGroups; - private RouteGroup mEditingGroup; - - // Temporary lists for manipulation - private final ArrayList<RouteInfo> mCatRouteList = new ArrayList<RouteInfo>(); - private final ArrayList<RouteInfo> mSortRouteList = new ArrayList<RouteInfo>(); - - private boolean mIgnoreUpdates; - - RouteAdapter() { - update(); - } - - void update() { - /* - * This is kind of wacky, but our data sets are going to be - * fairly small on average. Ideally we should be able to do some of this stuff - * in-place instead. - * - * Basic idea: each entry in mItems represents an item in the list for quick access. - * Entries can be a RouteCategory (section header), a RouteInfo with a category of - * mCategoryEditingGroups (a flattened RouteInfo pulled out of its group, allowing - * the user to change the group), - */ - if (mIgnoreUpdates) return; - - mItems.clear(); - - final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes); - mSelectedItemPosition = -1; - - List<RouteInfo> routes; - final int catCount = mRouter.getCategoryCount(); - for (int i = 0; i < catCount; i++) { - final RouteCategory cat = mRouter.getCategoryAt(i); - routes = cat.getRoutes(mCatRouteList); - - if (!cat.isSystem()) { - mItems.add(cat); - } - - if (cat == mCategoryEditingGroups) { - addGroupEditingCategoryRoutes(routes); - } else { - addSelectableRoutes(selectedRoute, routes); - } - - routes.clear(); + if (types != getRouteTypes()) { + Bundle args = getArguments(); + if (args == null) { + args = new Bundle(); } + args.putInt(ARGUMENT_ROUTE_TYPES, types); + setArguments(args); - notifyDataSetChanged(); - if (mListView != null && mSelectedItemPosition >= 0) { - mListView.setItemChecked(mSelectedItemPosition, true); - } - } - - void scrollToEditingGroup() { - if (mCategoryEditingGroups == null || mListView == null) return; - - int pos = 0; - int bound = 0; - final int itemCount = mItems.size(); - for (int i = 0; i < itemCount; i++) { - final Object item = mItems.get(i); - if (item != null && item == mCategoryEditingGroups) { - bound = i; - } - if (item == null) { - pos = i; - break; // this is always below the category header; we can stop here. - } - } - - mListView.smoothScrollToPosition(pos, bound); - } - - void scrollToSelectedItem() { - if (mListView == null || mSelectedItemPosition < 0) return; - - mListView.smoothScrollToPosition(mSelectedItemPosition); - } - - void addSelectableRoutes(RouteInfo selectedRoute, List<RouteInfo> from) { - final int routeCount = from.size(); - for (int j = 0; j < routeCount; j++) { - final RouteInfo info = from.get(j); - if (info == selectedRoute) { - mSelectedItemPosition = mItems.size(); - } - mItems.add(info); - } - } - - void addGroupEditingCategoryRoutes(List<RouteInfo> from) { - // Unpack groups and flatten for presentation - // mSortRouteList will always be empty here. - final int topCount = from.size(); - for (int i = 0; i < topCount; i++) { - final RouteInfo route = from.get(i); - final RouteGroup group = route.getGroup(); - if (group == route) { - // This is a group, unpack it. - final int groupCount = group.getRouteCount(); - for (int j = 0; j < groupCount; j++) { - final RouteInfo innerRoute = group.getRouteAt(j); - mSortRouteList.add(innerRoute); - } - } else { - mSortRouteList.add(route); - } - } - // Sort by name. This will keep the route positions relatively stable even though they - // will be repeatedly added and removed. - Collections.sort(mSortRouteList, mComparator); - - mItems.addAll(mSortRouteList); - mSortRouteList.clear(); - - mItems.add(null); // Sentinel reserving space for the "done" button. - } - - @Override - public int getCount() { - return mItems.size(); - } - - @Override - public int getViewTypeCount() { - return 5; - } - - @Override - public int getItemViewType(int position) { - final Object item = getItem(position); - if (item instanceof RouteCategory) { - return position == 0 ? VIEW_TOP_HEADER : VIEW_SECTION_HEADER; - } else if (item == null) { - return VIEW_GROUPING_DONE; - } else { - final RouteInfo info = (RouteInfo) item; - if (info.getCategory() == mCategoryEditingGroups) { - return VIEW_GROUPING_ROUTE; - } - return VIEW_ROUTE; - } - } - - @Override - public boolean areAllItemsEnabled() { - return false; - } - - @Override - public boolean isEnabled(int position) { - switch (getItemViewType(position)) { - case VIEW_ROUTE: - return ((RouteInfo) mItems.get(position)).isEnabled(); - case VIEW_GROUPING_ROUTE: - case VIEW_GROUPING_DONE: - return true; - default: - return false; - } - } - - @Override - public Object getItem(int position) { - return mItems.get(position); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - final int viewType = getItemViewType(position); - - ViewHolder holder; - if (convertView == null) { - convertView = mInflater.inflate(ITEM_LAYOUTS[viewType], parent, false); - holder = new ViewHolder(); - holder.position = position; - holder.text1 = (TextView) convertView.findViewById(R.id.text1); - holder.text2 = (TextView) convertView.findViewById(R.id.text2); - holder.icon = (ImageView) convertView.findViewById(R.id.icon); - holder.check = (CheckBox) convertView.findViewById(R.id.check); - holder.expandGroupButton = (ImageButton) convertView.findViewById( - R.id.expand_button); - if (holder.expandGroupButton != null) { - holder.expandGroupListener = new ExpandGroupListener(); - holder.expandGroupButton.setOnClickListener(holder.expandGroupListener); - } - - final View fview = convertView; - final ListView list = (ListView) parent; - final ViewHolder fholder = holder; - convertView.setOnClickListener(new View.OnClickListener() { - @Override public void onClick(View v) { - list.performItemClick(fview, fholder.position, 0); - } - }); - convertView.setTag(holder); - } else { - holder = (ViewHolder) convertView.getTag(); - holder.position = position; - } - - switch (viewType) { - case VIEW_ROUTE: - case VIEW_GROUPING_ROUTE: - bindItemView(position, holder); - break; - case VIEW_SECTION_HEADER: - case VIEW_TOP_HEADER: - bindHeaderView(position, holder); - break; - } - - convertView.setActivated(position == mSelectedItemPosition); - convertView.setEnabled(isEnabled(position)); - - return convertView; - } - - void bindItemView(int position, ViewHolder holder) { - RouteInfo info = (RouteInfo) mItems.get(position); - holder.text1.setText(info.getName(getActivity())); - final CharSequence status = info.getStatus(); - if (TextUtils.isEmpty(status)) { - holder.text2.setVisibility(View.GONE); - } else { - holder.text2.setVisibility(View.VISIBLE); - holder.text2.setText(status); - } - Drawable icon = info.getIconDrawable(); - if (icon != null) { - // Make sure we have a fresh drawable where it doesn't matter if we mutate it - icon = icon.getConstantState().newDrawable(getResources()); - } - holder.icon.setImageDrawable(icon); - holder.icon.setVisibility(icon != null ? View.VISIBLE : View.GONE); - - RouteCategory cat = info.getCategory(); - boolean canGroup = false; - if (cat == mCategoryEditingGroups) { - RouteGroup group = info.getGroup(); - holder.check.setEnabled(group.getRouteCount() > 1); - holder.check.setChecked(group == mEditingGroup); - } else { - if (cat.isGroupable()) { - final RouteGroup group = (RouteGroup) info; - canGroup = group.getRouteCount() > 1 || - getItemViewType(position - 1) == VIEW_ROUTE || - (position < getCount() - 1 && - getItemViewType(position + 1) == VIEW_ROUTE); - } - } - - if (holder.expandGroupButton != null) { - holder.expandGroupButton.setVisibility(canGroup ? View.VISIBLE : View.GONE); - holder.expandGroupListener.position = position; - } - } - - void bindHeaderView(int position, ViewHolder holder) { - RouteCategory cat = (RouteCategory) mItems.get(position); - holder.text1.setText(cat.getName(getActivity())); - } - - @Override - public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - final int type = getItemViewType(position); - if (type == VIEW_SECTION_HEADER || type == VIEW_TOP_HEADER) { - return; - } else if (type == VIEW_GROUPING_DONE) { - finishGrouping(); - return; - } else { - final Object item = getItem(position); - if (!(item instanceof RouteInfo)) { - // Oops. Stale event running around? Skip it. - return; - } - - final RouteInfo route = (RouteInfo) item; - if (type == VIEW_ROUTE) { - mRouter.selectRouteInt(mRouteTypes, route); - dismiss(); - } else if (type == VIEW_GROUPING_ROUTE) { - final Checkable c = (Checkable) view; - final boolean wasChecked = c.isChecked(); - - mIgnoreUpdates = true; - RouteGroup oldGroup = route.getGroup(); - if (!wasChecked && oldGroup != mEditingGroup) { - // Assumption: in a groupable category oldGroup will never be null. - if (mRouter.getSelectedRoute(mRouteTypes) == oldGroup) { - // Old group was selected but is now empty. Select the group - // we're manipulating since that's where the last route went. - mRouter.selectRouteInt(mRouteTypes, mEditingGroup); - } - oldGroup.removeRoute(route); - mEditingGroup.addRoute(route); - c.setChecked(true); - } else if (wasChecked && mEditingGroup.getRouteCount() > 1) { - mEditingGroup.removeRoute(route); - - // In a groupable category this will add - // the route into its own new group. - mRouter.addRouteInt(route); - } - mIgnoreUpdates = false; - update(); - } - } - } - - boolean isGrouping() { - return mCategoryEditingGroups != null; - } - - void finishGrouping() { - mCategoryEditingGroups = null; - mEditingGroup = null; - getDialog().setCanceledOnTouchOutside(true); - update(); - scrollToSelectedItem(); - } - - class ExpandGroupListener implements View.OnClickListener { - int position; - - @Override - public void onClick(View v) { - // Assumption: this is only available for the user to click if we're presenting - // a groupable category, where every top-level route in the category is a group. - final RouteGroup group = (RouteGroup) getItem(position); - mEditingGroup = group; - mCategoryEditingGroups = group.getCategory(); - getDialog().setCanceledOnTouchOutside(false); - mRouter.selectRouteInt(mRouteTypes, mEditingGroup); - update(); - scrollToEditingGroup(); - } - } - } - - class MediaRouterCallback extends MediaRouter.Callback { - @Override - public void onRouteSelected(MediaRouter router, int type, RouteInfo info) { - mAdapter.update(); - updateVolume(); - } - - @Override - public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) { - mAdapter.update(); - } - - @Override - public void onRouteAdded(MediaRouter router, RouteInfo info) { - mAdapter.update(); - } - - @Override - public void onRouteRemoved(MediaRouter router, RouteInfo info) { - if (info == mAdapter.mEditingGroup) { - mAdapter.finishGrouping(); - } - mAdapter.update(); - } - - @Override - public void onRouteChanged(MediaRouter router, RouteInfo info) { - mAdapter.notifyDataSetChanged(); - } - - @Override - public void onRouteGrouped(MediaRouter router, RouteInfo info, - RouteGroup group, int index) { - mAdapter.update(); - } - - @Override - public void onRouteUngrouped(MediaRouter router, RouteInfo info, RouteGroup group) { - mAdapter.update(); - } - - @Override - public void onRouteVolumeChanged(MediaRouter router, RouteInfo info) { - if (!mIgnoreCallbackVolumeChanges) { - updateVolume(); + MediaRouteChooserDialog dialog = (MediaRouteChooserDialog)getDialog(); + if (dialog != null) { + dialog.setRouteTypes(types); } } } - class RouteComparator implements Comparator<RouteInfo> { - @Override - public int compare(RouteInfo lhs, RouteInfo rhs) { - return lhs.getName(getActivity()).toString() - .compareTo(rhs.getName(getActivity()).toString()); - } - } - - class RouteChooserDialog extends Dialog { - public RouteChooserDialog(Context context, int theme) { - super(context, theme); - } - - @Override - public void onBackPressed() { - if (mAdapter != null && mAdapter.isGrouping()) { - mAdapter.finishGrouping(); - } else { - super.onBackPressed(); - } - } - - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mVolumeSlider.isEnabled()) { - final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes); - if (selectedRoute != null) { - selectedRoute.requestUpdateVolume(-1); - return true; - } - } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mVolumeSlider.isEnabled()) { - final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes); - if (selectedRoute != null) { - mRouter.getSelectedRoute(mRouteTypes).requestUpdateVolume(1); - return true; - } - } - return super.onKeyDown(keyCode, event); - } + public void setExtendedSettingsClickListener(View.OnClickListener listener) { + if (listener != mExtendedSettingsClickListener) { + mExtendedSettingsClickListener = listener; - public boolean onKeyUp(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mVolumeSlider.isEnabled()) { - return true; - } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mVolumeSlider.isEnabled()) { - return true; - } else { - return super.onKeyUp(keyCode, event); + MediaRouteChooserDialog dialog = (MediaRouteChooserDialog)getDialog(); + if (dialog != null) { + dialog.setExtendedSettingsClickListener(listener); } } } /** - * Implemented by the MediaRouteButton that launched this dialog + * Called when the chooser dialog is being created. + * <p> + * Subclasses may override this method to customize the dialog. + * </p> */ - public interface LauncherListener { - public void onDetached(MediaRouteChooserDialogFragment detachedFragment); + public MediaRouteChooserDialog onCreateChooserDialog( + Context context, Bundle savedInstanceState) { + return new MediaRouteChooserDialog(context, getTheme()); } - class VolumeSliderChangeListener implements SeekBar.OnSeekBarChangeListener { - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - changeVolume(progress); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - mIgnoreCallbackVolumeChanges = true; - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - mIgnoreCallbackVolumeChanges = false; - updateVolume(); - } - + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + MediaRouteChooserDialog dialog = onCreateChooserDialog(getActivity(), savedInstanceState); + dialog.setRouteTypes(getRouteTypes()); + dialog.setExtendedSettingsClickListener(mExtendedSettingsClickListener); + return dialog; } } diff --git a/core/java/com/android/internal/app/MediaRouteControllerDialog.java b/core/java/com/android/internal/app/MediaRouteControllerDialog.java new file mode 100644 index 0000000..8fc99c7 --- /dev/null +++ b/core/java/com/android/internal/app/MediaRouteControllerDialog.java @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.app; + +import com.android.internal.R; + +import android.app.Dialog; +import android.app.MediaRouteActionProvider; +import android.app.MediaRouteButton; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.media.MediaRouter; +import android.media.MediaRouter.RouteGroup; +import android.media.MediaRouter.RouteInfo; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; +import android.view.Window; +import android.widget.Button; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.SeekBar; + +/** + * This class implements the route controller dialog for {@link MediaRouter}. + * <p> + * This dialog allows the user to control or disconnect from the currently selected route. + * </p> + * + * @see MediaRouteButton + * @see MediaRouteActionProvider + * + * TODO: Move this back into the API, as in the support library media router. + */ +public class MediaRouteControllerDialog extends Dialog { + // Time to wait before updating the volume when the user lets go of the seek bar + // to allow the route provider time to propagate the change and publish a new + // route descriptor. + private static final int VOLUME_UPDATE_DELAY_MILLIS = 250; + + private final MediaRouter mRouter; + private final MediaRouterCallback mCallback; + private final MediaRouter.RouteInfo mRoute; + + private boolean mCreated; + private Drawable mMediaRouteConnectingDrawable; + private Drawable mMediaRouteOnDrawable; + private Drawable mCurrentIconDrawable; + + private boolean mVolumeControlEnabled = true; + private LinearLayout mVolumeLayout; + private SeekBar mVolumeSlider; + private boolean mVolumeSliderTouched; + + private View mControlView; + + private Button mDisconnectButton; + + public MediaRouteControllerDialog(Context context, int theme) { + super(context, theme); + + mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE); + mCallback = new MediaRouterCallback(); + mRoute = mRouter.getSelectedRoute(); + } + + /** + * Gets the route that this dialog is controlling. + */ + public MediaRouter.RouteInfo getRoute() { + return mRoute; + } + + /** + * Provides the subclass an opportunity to create a view that will + * be included within the body of the dialog to offer additional media controls + * for the currently playing content. + * + * @param savedInstanceState The dialog's saved instance state. + * @return The media control view, or null if none. + */ + public View onCreateMediaControlView(Bundle savedInstanceState) { + return null; + } + + /** + * Gets the media control view that was created by {@link #onCreateMediaControlView(Bundle)}. + * + * @return The media control view, or null if none. + */ + public View getMediaControlView() { + return mControlView; + } + + /** + * Sets whether to enable the volume slider and volume control using the volume keys + * when the route supports it. + * <p> + * The default value is true. + * </p> + */ + public void setVolumeControlEnabled(boolean enable) { + if (mVolumeControlEnabled != enable) { + mVolumeControlEnabled = enable; + if (mCreated) { + updateVolume(); + } + } + } + + /** + * Returns whether to enable the volume slider and volume control using the volume keys + * when the route supports it. + */ + public boolean isVolumeControlEnabled() { + return mVolumeControlEnabled; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + getWindow().requestFeature(Window.FEATURE_LEFT_ICON); + + setContentView(R.layout.media_route_controller_dialog); + + mVolumeLayout = (LinearLayout)findViewById(R.id.media_route_volume_layout); + mVolumeSlider = (SeekBar)findViewById(R.id.media_route_volume_slider); + mVolumeSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + private final Runnable mStopTrackingTouch = new Runnable() { + @Override + public void run() { + if (mVolumeSliderTouched) { + mVolumeSliderTouched = false; + updateVolume(); + } + } + }; + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + if (mVolumeSliderTouched) { + mVolumeSlider.removeCallbacks(mStopTrackingTouch); + } else { + mVolumeSliderTouched = true; + } + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // Defer resetting mVolumeSliderTouched to allow the media route provider + // a little time to settle into its new state and publish the final + // volume update. + mVolumeSlider.postDelayed(mStopTrackingTouch, VOLUME_UPDATE_DELAY_MILLIS); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) { + mRoute.requestSetVolume(progress); + } + } + }); + + mDisconnectButton = (Button)findViewById(R.id.media_route_disconnect_button); + mDisconnectButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mRoute.isSelected()) { + mRouter.getDefaultRoute().select(); + } + dismiss(); + } + }); + + mCreated = true; + if (update()) { + mControlView = onCreateMediaControlView(savedInstanceState); + FrameLayout controlFrame = + (FrameLayout)findViewById(R.id.media_route_control_frame); + if (mControlView != null) { + controlFrame.addView(mControlView); + controlFrame.setVisibility(View.VISIBLE); + } else { + controlFrame.setVisibility(View.GONE); + } + } + } + + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + + mRouter.addCallback(0, mCallback, MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS); + update(); + } + + @Override + public void onDetachedFromWindow() { + mRouter.removeCallback(mCallback); + + super.onDetachedFromWindow(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN + || keyCode == KeyEvent.KEYCODE_VOLUME_UP) { + mRoute.requestUpdateVolume(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ? -1 : 1); + return true; + } + return super.onKeyDown(keyCode, event); + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN + || keyCode == KeyEvent.KEYCODE_VOLUME_UP) { + return true; + } + return super.onKeyUp(keyCode, event); + } + + private boolean update() { + if (!mRoute.isSelected() || mRoute.isDefault()) { + dismiss(); + return false; + } + + setTitle(mRoute.getName()); + updateVolume(); + + Drawable icon = getIconDrawable(); + if (icon != mCurrentIconDrawable) { + mCurrentIconDrawable = icon; + getWindow().setFeatureDrawable(Window.FEATURE_LEFT_ICON, icon); + } + return true; + } + + private Drawable getIconDrawable() { + if (mRoute.isConnecting()) { + if (mMediaRouteConnectingDrawable == null) { + mMediaRouteConnectingDrawable = getContext().getResources().getDrawable( + R.drawable.ic_media_route_connecting_holo_dark); + } + return mMediaRouteConnectingDrawable; + } else { + if (mMediaRouteOnDrawable == null) { + mMediaRouteOnDrawable = getContext().getResources().getDrawable( + R.drawable.ic_media_route_on_holo_dark); + } + return mMediaRouteOnDrawable; + } + } + + private void updateVolume() { + if (!mVolumeSliderTouched) { + if (isVolumeControlAvailable()) { + mVolumeLayout.setVisibility(View.VISIBLE); + mVolumeSlider.setMax(mRoute.getVolumeMax()); + mVolumeSlider.setProgress(mRoute.getVolume()); + } else { + mVolumeLayout.setVisibility(View.GONE); + } + } + } + + private boolean isVolumeControlAvailable() { + return mVolumeControlEnabled && mRoute.getVolumeHandling() == + MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE; + } + + private final class MediaRouterCallback extends MediaRouter.SimpleCallback { + @Override + public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) { + update(); + } + + @Override + public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) { + update(); + } + + @Override + public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo route) { + if (route == mRoute) { + updateVolume(); + } + } + + @Override + public void onRouteGrouped(MediaRouter router, RouteInfo info, RouteGroup group, + int index) { + update(); + } + + @Override + public void onRouteUngrouped(MediaRouter router, RouteInfo info, RouteGroup group) { + update(); + } + } +} diff --git a/core/java/com/android/internal/app/MediaRouteControllerDialogFragment.java b/core/java/com/android/internal/app/MediaRouteControllerDialogFragment.java new file mode 100644 index 0000000..108e81f --- /dev/null +++ b/core/java/com/android/internal/app/MediaRouteControllerDialogFragment.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.app; + +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.Context; +import android.os.Bundle; + +/** + * Media route controller dialog fragment. + * <p> + * Creates a {@link MediaRouteControllerDialog}. The application may subclass + * this dialog fragment to customize the media route controller dialog. + * </p> + * + * TODO: Move this back into the API, as in the support library media router. + */ +public class MediaRouteControllerDialogFragment extends DialogFragment { + /** + * Creates a media route controller dialog fragment. + * <p> + * All subclasses of this class must also possess a default constructor. + * </p> + */ + public MediaRouteControllerDialogFragment() { + setCancelable(true); + setStyle(STYLE_NORMAL, android.R.style.Theme_DeviceDefault_Dialog); + } + + /** + * Called when the controller dialog is being created. + * <p> + * Subclasses may override this method to customize the dialog. + * </p> + */ + public MediaRouteControllerDialog onCreateControllerDialog( + Context context, Bundle savedInstanceState) { + return new MediaRouteControllerDialog(context, getTheme()); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + return onCreateControllerDialog(getActivity(), savedInstanceState); + } +} diff --git a/core/java/com/android/internal/app/MediaRouteDialogPresenter.java b/core/java/com/android/internal/app/MediaRouteDialogPresenter.java new file mode 100644 index 0000000..fad7fd4 --- /dev/null +++ b/core/java/com/android/internal/app/MediaRouteDialogPresenter.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.app; + + +import android.app.Activity; +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.FragmentManager; +import android.content.Context; +import android.media.MediaRouter; +import android.util.Log; +import android.view.View; + +/** + * Shows media route dialog as appropriate. + * @hide + */ +public abstract class MediaRouteDialogPresenter { + private static final String TAG = "MediaRouter"; + + private static final String CHOOSER_FRAGMENT_TAG = + "android.app.MediaRouteButton:MediaRouteChooserDialogFragment"; + private static final String CONTROLLER_FRAGMENT_TAG = + "android.app.MediaRouteButton:MediaRouteControllerDialogFragment"; + + public static DialogFragment showDialogFragment(Activity activity, + int routeTypes, View.OnClickListener extendedSettingsClickListener) { + final MediaRouter router = (MediaRouter)activity.getSystemService( + Context.MEDIA_ROUTER_SERVICE); + final FragmentManager fm = activity.getFragmentManager(); + + MediaRouter.RouteInfo route = router.getSelectedRoute(); + if (route.isDefault() || !route.matchesTypes(routeTypes)) { + if (fm.findFragmentByTag(CHOOSER_FRAGMENT_TAG) != null) { + Log.w(TAG, "showDialog(): Route chooser dialog already showing!"); + return null; + } + MediaRouteChooserDialogFragment f = new MediaRouteChooserDialogFragment(); + f.setRouteTypes(routeTypes); + f.setExtendedSettingsClickListener(extendedSettingsClickListener); + f.show(fm, CHOOSER_FRAGMENT_TAG); + return f; + } else { + if (fm.findFragmentByTag(CONTROLLER_FRAGMENT_TAG) != null) { + Log.w(TAG, "showDialog(): Route controller dialog already showing!"); + return null; + } + MediaRouteControllerDialogFragment f = new MediaRouteControllerDialogFragment(); + f.show(fm, CONTROLLER_FRAGMENT_TAG); + return f; + } + } + + public static Dialog createDialog(Context context, + int routeTypes, View.OnClickListener extendedSettingsClickListener) { + final MediaRouter router = (MediaRouter)context.getSystemService( + Context.MEDIA_ROUTER_SERVICE); + + MediaRouter.RouteInfo route = router.getSelectedRoute(); + if (route.isDefault() || !route.matchesTypes(routeTypes)) { + final MediaRouteChooserDialog d = new MediaRouteChooserDialog( + context, android.R.style.Theme_DeviceDefault_Dialog); + d.setRouteTypes(routeTypes); + d.setExtendedSettingsClickListener(extendedSettingsClickListener); + return d; + } else { + MediaRouteControllerDialog d = new MediaRouteControllerDialog( + context, android.R.style.Theme_DeviceDefault_Dialog); + return d; + } + } +} diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java index 20b8c95..0cad33c 100644 --- a/core/java/com/android/internal/app/ProcessStats.java +++ b/core/java/com/android/internal/app/ProcessStats.java @@ -1758,21 +1758,34 @@ public final class ProcessStats implements Parcelable { mStartTime, now); ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap(); boolean printedHeader = false; + boolean sepNeeded = false; for (int ip=0; ip<pkgMap.size(); ip++) { - String pkgName = pkgMap.keyAt(ip); - if (reqPackage != null && !reqPackage.equals(pkgName)) { - continue; - } - SparseArray<PackageState> uids = pkgMap.valueAt(ip); + final String pkgName = pkgMap.keyAt(ip); + final SparseArray<PackageState> uids = pkgMap.valueAt(ip); for (int iu=0; iu<uids.size(); iu++) { - int uid = uids.keyAt(iu); - PackageState pkgState = uids.valueAt(iu); + final int uid = uids.keyAt(iu); + final PackageState pkgState = uids.valueAt(iu); final int NPROCS = pkgState.mProcesses.size(); final int NSRVS = pkgState.mServices.size(); + final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName); + if (!pkgMatch) { + boolean procMatch = false; + for (int iproc=0; iproc<NPROCS; iproc++) { + ProcessState proc = pkgState.mProcesses.valueAt(iproc); + if (reqPackage.equals(proc.mName)) { + procMatch = true; + break; + } + } + if (!procMatch) { + continue; + } + } if (NPROCS > 0 || NSRVS > 0) { if (!printedHeader) { pw.println("Per-Package Stats:"); printedHeader = true; + sepNeeded = true; } pw.print(" * "); pw.print(pkgName); pw.print(" / "); UserHandle.formatUid(pw, uid); pw.println(":"); @@ -1780,6 +1793,9 @@ public final class ProcessStats implements Parcelable { if (!dumpSummary || dumpAll) { for (int iproc=0; iproc<NPROCS; iproc++) { ProcessState proc = pkgState.mProcesses.valueAt(iproc); + if (!pkgMatch && !reqPackage.equals(proc.mName)) { + continue; + } if (activeOnly && !proc.isInUse()) { pw.print(" (Not active: "); pw.print(pkgState.mProcesses.keyAt(iproc)); pw.println(")"); @@ -1787,7 +1803,11 @@ public final class ProcessStats implements Parcelable { } pw.print(" Process "); pw.print(pkgState.mProcesses.keyAt(iproc)); - pw.print(" ("); + if (proc.mCommonProcess.mMultiPackage) { + pw.print(" (multi, "); + } else { + pw.print(" (unique, "); + } pw.print(proc.mDurationsTableSize); pw.print(" entries)"); pw.println(":"); @@ -1801,6 +1821,9 @@ public final class ProcessStats implements Parcelable { ArrayList<ProcessState> procs = new ArrayList<ProcessState>(); for (int iproc=0; iproc<NPROCS; iproc++) { ProcessState proc = pkgState.mProcesses.valueAt(iproc); + if (!pkgMatch && !reqPackage.equals(proc.mName)) { + continue; + } if (activeOnly && !proc.isInUse()) { continue; } @@ -1811,6 +1834,9 @@ public final class ProcessStats implements Parcelable { } for (int isvc=0; isvc<NSRVS; isvc++) { ServiceState svc = pkgState.mServices.valueAt(isvc); + if (!pkgMatch && !reqPackage.equals(svc.mProcessName)) { + continue; + } if (activeOnly && !svc.isInUse()) { pw.print(" (Not active: "); pw.print(pkgState.mServices.keyAt(isvc)); pw.println(")"); @@ -1840,64 +1866,73 @@ public final class ProcessStats implements Parcelable { if (svc.mOwner != null) { pw.print(" mOwner="); pw.println(svc.mOwner); } + if (svc.mStarted || svc.mRestarting) { + pw.print(" mStarted="); pw.print(svc.mStarted); + pw.print(" mRestarting="); pw.println(svc.mRestarting); + } } } } } - if (reqPackage == null) { - ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); - printedHeader = false; - int numShownProcs = 0, numTotalProcs = 0; - for (int ip=0; ip<procMap.size(); ip++) { - String procName = procMap.keyAt(ip); - SparseArray<ProcessState> uids = procMap.valueAt(ip); - for (int iu=0; iu<uids.size(); iu++) { - int uid = uids.keyAt(iu); - numTotalProcs++; - ProcessState proc = uids.valueAt(iu); - if (proc.mDurationsTableSize == 0 && proc.mCurState == STATE_NOTHING - && proc.mPssTableSize == 0) { - continue; - } - numShownProcs++; - if (!printedHeader) { - pw.println(); - pw.println("Per-Process Stats:"); - printedHeader = true; - } - if (activeOnly && !proc.isInUse()) { - pw.print(" (Not active: "); pw.print(procName); pw.println(")"); - continue; - } - pw.print(" * "); pw.print(procName); pw.print(" / "); - UserHandle.formatUid(pw, uid); - pw.print(" ("); pw.print(proc.mDurationsTableSize); - pw.print(" entries)"); pw.println(":"); - dumpProcessState(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ, - ALL_PROC_STATES, now); - dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ, - ALL_PROC_STATES); - if (dumpAll) { - dumpProcessInternalLocked(pw, " ", proc, dumpAll); - } + ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap(); + printedHeader = false; + int numShownProcs = 0, numTotalProcs = 0; + for (int ip=0; ip<procMap.size(); ip++) { + String procName = procMap.keyAt(ip); + SparseArray<ProcessState> uids = procMap.valueAt(ip); + for (int iu=0; iu<uids.size(); iu++) { + int uid = uids.keyAt(iu); + numTotalProcs++; + ProcessState proc = uids.valueAt(iu); + if (proc.mDurationsTableSize == 0 && proc.mCurState == STATE_NOTHING + && proc.mPssTableSize == 0) { + continue; } + if (!proc.mMultiPackage) { + continue; + } + if (reqPackage != null && !reqPackage.equals(procName) + && !reqPackage.equals(proc.mPackage)) { + continue; + } + numShownProcs++; + if (sepNeeded) { + pw.println(); + } + sepNeeded = true; + if (!printedHeader) { + pw.println("Multi-Package Common Processes:"); + printedHeader = true; + } + if (activeOnly && !proc.isInUse()) { + pw.print(" (Not active: "); pw.print(procName); pw.println(")"); + continue; + } + pw.print(" * "); pw.print(procName); pw.print(" / "); + UserHandle.formatUid(pw, uid); + pw.print(" ("); pw.print(proc.mDurationsTableSize); + pw.print(" entries)"); pw.println(":"); + dumpProcessState(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ, + ALL_PROC_STATES, now); + dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ, + ALL_PROC_STATES); + dumpProcessInternalLocked(pw, " ", proc, dumpAll); } - if (dumpAll) { - pw.println(); - pw.print(" Total procs: "); pw.print(numShownProcs); - pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total"); - } + } + if (dumpAll) { + pw.println(); + pw.print(" Total procs: "); pw.print(numShownProcs); + pw.print(" shown of "); pw.print(numTotalProcs); pw.println(" total"); + } + if (sepNeeded) { pw.println(); - if (dumpSummary) { - pw.println("Summary:"); - dumpSummaryLocked(pw, reqPackage, now, activeOnly); - } else { - dumpTotalsLocked(pw, now); - } + } + if (dumpSummary) { + pw.println("Summary:"); + dumpSummaryLocked(pw, reqPackage, now, activeOnly); } else { - pw.println(); dumpTotalsLocked(pw, now); } @@ -2031,17 +2066,20 @@ public final class ProcessStats implements Parcelable { public ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates, int[] procStates, int sortProcStates[], long now, String reqPackage, boolean activeOnly) { - ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>(); - ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap(); + final ArraySet<ProcessState> foundProcs = new ArraySet<ProcessState>(); + final ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap(); for (int ip=0; ip<pkgMap.size(); ip++) { - if (reqPackage != null && !reqPackage.equals(pkgMap.keyAt(ip))) { - continue; - } - SparseArray<PackageState> procs = pkgMap.valueAt(ip); + final String pkgName = pkgMap.keyAt(ip); + final SparseArray<PackageState> procs = pkgMap.valueAt(ip); for (int iu=0; iu<procs.size(); iu++) { - PackageState state = procs.valueAt(iu); - for (int iproc=0; iproc<state.mProcesses.size(); iproc++) { - ProcessState proc = state.mProcesses.valueAt(iproc); + final PackageState state = procs.valueAt(iu); + final int NPROCS = state.mProcesses.size(); + final boolean pkgMatch = reqPackage == null || reqPackage.equals(pkgName); + for (int iproc=0; iproc<NPROCS; iproc++) { + final ProcessState proc = state.mProcesses.valueAt(iproc); + if (!pkgMatch && !reqPackage.equals(proc.mName)) { + continue; + } if (activeOnly && !proc.isInUse()) { continue; } @@ -2601,23 +2639,35 @@ public final class ProcessStats implements Parcelable { } } - void incStartedServices(int memFactor, long now) { + void incStartedServices(int memFactor, long now, String serviceName) { + if (false) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.d(TAG, "incStartedServices: " + this + " service=" + serviceName + + " to " + (mNumStartedServices+1), here); + } if (mCommonProcess != this) { - mCommonProcess.incStartedServices(memFactor, now); + mCommonProcess.incStartedServices(memFactor, now, serviceName); } mNumStartedServices++; if (mNumStartedServices == 1 && mCurState == STATE_NOTHING) { - setState(STATE_NOTHING, memFactor, now, null); + setState(STATE_SERVICE_RESTARTING + (memFactor*STATE_COUNT), now); } } - void decStartedServices(int memFactor, long now) { + void decStartedServices(int memFactor, long now, String serviceName) { + if (false) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.d(TAG, "decActiveServices: " + this + " service=" + serviceName + + " to " + (mNumStartedServices-1), here); + } if (mCommonProcess != this) { - mCommonProcess.decStartedServices(memFactor, now); + mCommonProcess.decStartedServices(memFactor, now, serviceName); } mNumStartedServices--; - if (mNumStartedServices == 0 && mCurState == STATE_SERVICE_RESTARTING) { - setState(STATE_NOTHING, memFactor, now, null); + if (mNumStartedServices == 0 && (mCurState%STATE_COUNT) == STATE_SERVICE_RESTARTING) { + setState(STATE_NOTHING, now); } else if (mNumStartedServices < 0) { Slog.wtfStack(TAG, "Proc started services underrun: pkg=" + mPackage + " uid=" + mUid + " name=" + mName); @@ -2873,6 +2923,8 @@ public final class ProcessStats implements Parcelable { public int mRunState = STATE_NOTHING; long mRunStartTime; + boolean mStarted; + boolean mRestarting; int mStartedCount; public int mStartedState = STATE_NOTHING; long mStartedStartTime; @@ -2902,10 +2954,9 @@ public final class ProcessStats implements Parcelable { // There was already an old owner, reset this object for its // new owner. mOwner = newOwner; - if (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING - || mExecState != STATE_NOTHING) { + if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) { long now = SystemClock.uptimeMillis(); - if (mStartedState != STATE_NOTHING) { + if (mStarted) { if (DEBUG) Slog.d(TAG, "Service has new owner " + newOwner + " from " + mOwner + " while started: pkg=" + mPackage + " service=" + mName + " proc=" + mProc); @@ -2931,10 +2982,9 @@ public final class ProcessStats implements Parcelable { public void clearCurrentOwner(Object owner, boolean silently) { if (mOwner == owner) { mProc.decActiveServices(mName); - if (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING - || mExecState != STATE_NOTHING) { + if (mStarted || mBoundState != STATE_NOTHING || mExecState != STATE_NOTHING) { long now = SystemClock.uptimeMillis(); - if (mStartedState != STATE_NOTHING) { + if (mStarted) { if (!silently) { Slog.wtfStack(TAG, "Service owner " + owner + " cleared while started: pkg=" + mPackage + " service=" @@ -3042,7 +3092,18 @@ public final class ProcessStats implements Parcelable { if (mOwner == null) { Slog.wtf(TAG, "Starting service " + this + " without owner"); } + mStarted = started; + updateStartedState(memFactor, now); + } + + public void setRestarting(boolean restarting, int memFactor, long now) { + mRestarting = restarting; + updateStartedState(memFactor, now); + } + + void updateStartedState(int memFactor, long now) { final boolean wasStarted = mStartedState != STATE_NOTHING; + final boolean started = mStarted || mRestarting; final int state = started ? memFactor : STATE_NOTHING; if (mStartedState != state) { if (mStartedState != STATE_NOTHING) { @@ -3056,9 +3117,9 @@ public final class ProcessStats implements Parcelable { mProc = mProc.pullFixedProc(mPackage); if (wasStarted != started) { if (started) { - mProc.incStartedServices(memFactor, now); + mProc.incStartedServices(memFactor, now, mName); } else { - mProc.decStartedServices(memFactor, now); + mProc.decStartedServices(memFactor, now, mName); } } updateRunning(memFactor, now); diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl index 5bfa1b2..1e37fd9 100644 --- a/core/java/com/android/internal/backup/IBackupTransport.aidl +++ b/core/java/com/android/internal/backup/IBackupTransport.aidl @@ -23,6 +23,12 @@ import android.os.ParcelFileDescriptor; /** {@hide} */ interface IBackupTransport { + /** + * Ask the transport for the name under which it should be registered. This will + * typically be its host service's component name, but need not be. + */ + String name(); + /** * Ask the transport for an Intent that can be used to launch any internal * configuration Activity that it wishes to present. For example, the transport diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java index eb2d1fe..494bc78 100644 --- a/core/java/com/android/internal/backup/LocalTransport.java +++ b/core/java/com/android/internal/backup/LocalTransport.java @@ -19,6 +19,7 @@ package com.android.internal.backup; import android.app.backup.BackupDataInput; import android.app.backup.BackupDataOutput; import android.app.backup.RestoreSet; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; @@ -71,6 +72,10 @@ public class LocalTransport extends IBackupTransport.Stub { } } + public String name() { + return new ComponentName(mContext, this.getClass()).flattenToShortString(); + } + public Intent configurationIntent() { // The local transport is not user-configurable return null; diff --git a/core/java/com/android/internal/backup/LocalTransportService.java b/core/java/com/android/internal/backup/LocalTransportService.java new file mode 100644 index 0000000..d05699a --- /dev/null +++ b/core/java/com/android/internal/backup/LocalTransportService.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.backup; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; + +public class LocalTransportService extends Service { + private static LocalTransport sTransport = null; + + @Override + public void onCreate() { + if (sTransport == null) { + sTransport = new LocalTransport(this); + } + } + + @Override + public IBinder onBind(Intent intent) { + return sTransport; + } +} diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index a99aa33..0a702ff 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -84,7 +84,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 66 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 67 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -154,6 +154,8 @@ public final class BatteryStatsImpl extends BatteryStats { final ArrayList<StopwatchTimer> mFullWifiLockTimers = new ArrayList<StopwatchTimer>(); final ArrayList<StopwatchTimer> mWifiMulticastTimers = new ArrayList<StopwatchTimer>(); final ArrayList<StopwatchTimer> mWifiScanTimers = new ArrayList<StopwatchTimer>(); + final SparseArray<ArrayList<StopwatchTimer>> mWifiBatchedScanTimers = + new SparseArray<ArrayList<StopwatchTimer>>(); // Last partial timers we use for distributing CPU usage. final ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<StopwatchTimer>(); @@ -2404,6 +2406,14 @@ public final class BatteryStatsImpl extends BatteryStats { getUidStatsLocked(uid).noteWifiScanStoppedLocked(); } + public void noteWifiBatchedScanStartedLocked(int uid, int csph) { + getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph); + } + + public void noteWifiBatchedScanStoppedLocked(int uid) { + getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(); + } + int mWifiMulticastNesting = 0; public void noteWifiMulticastEnabledLocked(int uid) { @@ -2456,6 +2466,20 @@ public final class BatteryStatsImpl extends BatteryStats { } } + public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) { + int N = ws.size(); + for (int i=0; i<N; i++) { + noteWifiBatchedScanStartedLocked(ws.get(i), csph); + } + } + + public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) { + int N = ws.size(); + for (int i=0; i<N; i++) { + noteWifiBatchedScanStoppedLocked(ws.get(i)); + } + } + public void noteWifiMulticastEnabledFromSourceLocked(WorkSource ws) { int N = ws.size(); for (int i=0; i<N; i++) { @@ -2579,6 +2603,10 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mWifiScanStarted; StopwatchTimer mWifiScanTimer; + private static final int NO_BATCHED_SCAN_STARTED = -1; + int mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED; + StopwatchTimer[] mWifiBatchedScanTimer; + boolean mWifiMulticastEnabled; StopwatchTimer mWifiMulticastTimer; @@ -2629,6 +2657,7 @@ public final class BatteryStatsImpl extends BatteryStats { mFullWifiLockTimers, mUnpluggables); mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN, mWifiScanTimers, mUnpluggables); + mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS]; mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED, mWifiMulticastTimers, mUnpluggables); } @@ -2719,6 +2748,36 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override + public void noteWifiBatchedScanStartedLocked(int csph) { + int bin = 0; + while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS) { + csph = csph >> 3; + bin++; + } + + if (mWifiBatchedScanBinStarted == bin) return; + + if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) { + mWifiBatchedScanTimer[mWifiBatchedScanBinStarted]. + stopRunningLocked(BatteryStatsImpl.this); + } + mWifiBatchedScanBinStarted = bin; + if (mWifiBatchedScanTimer[bin] == null) { + makeWifiBatchedScanBin(bin, null); + } + mWifiBatchedScanTimer[bin].startRunningLocked(BatteryStatsImpl.this); + } + + @Override + public void noteWifiBatchedScanStoppedLocked() { + if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) { + mWifiBatchedScanTimer[mWifiBatchedScanBinStarted]. + stopRunningLocked(BatteryStatsImpl.this); + mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED; + } + } + + @Override public void noteWifiMulticastEnabledLocked() { if (!mWifiMulticastEnabled) { mWifiMulticastEnabled = true; @@ -2854,6 +2913,15 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override + public long getWifiBatchedScanTime(int csphBin, long batteryRealtime, int which) { + if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0; + if (mWifiBatchedScanTimer[csphBin] == null) { + return 0; + } + return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(batteryRealtime, which); + } + + @Override public long getWifiMulticastTime(long batteryRealtime, int which) { if (mWifiMulticastTimer == null) { return 0; @@ -2914,6 +2982,24 @@ public final class BatteryStatsImpl extends BatteryStats { return mUserActivityCounters[type].getCountLocked(which); } + void makeWifiBatchedScanBin(int i, Parcel in) { + if (i < 0 || i >= NUM_WIFI_BATCHED_SCAN_BINS) return; + + ArrayList<StopwatchTimer> collected = mWifiBatchedScanTimers.get(i); + if (collected == null) { + collected = new ArrayList<StopwatchTimer>(); + mWifiBatchedScanTimers.put(i, collected); + } + if (in == null) { + mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected, + mUnpluggables); + } else { + mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected, + mUnpluggables, in); + } + } + + void initUserActivityLocked() { mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES]; for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { @@ -2974,6 +3060,14 @@ public final class BatteryStatsImpl extends BatteryStats { active |= !mWifiScanTimer.reset(BatteryStatsImpl.this, false); active |= mWifiScanStarted; } + if (mWifiBatchedScanTimer != null) { + for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) { + if (mWifiBatchedScanTimer[i] != null) { + active |= !mWifiBatchedScanTimer[i].reset(BatteryStatsImpl.this, false); + } + } + active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED); + } if (mWifiMulticastTimer != null) { active |= !mWifiMulticastTimer.reset(BatteryStatsImpl.this, false); active |= mWifiMulticastEnabled; @@ -3080,6 +3174,11 @@ public final class BatteryStatsImpl extends BatteryStats { if (mWifiScanTimer != null) { mWifiScanTimer.detach(); } + for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) { + if (mWifiBatchedScanTimer[i] != null) { + mWifiBatchedScanTimer[i].detach(); + } + } if (mWifiMulticastTimer != null) { mWifiMulticastTimer.detach(); } @@ -3157,6 +3256,14 @@ public final class BatteryStatsImpl extends BatteryStats { } else { out.writeInt(0); } + for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) { + if (mWifiBatchedScanTimer[i] != null) { + out.writeInt(1); + mWifiBatchedScanTimer[i].writeToParcel(out, batteryRealtime); + } else { + out.writeInt(0); + } + } if (mWifiMulticastTimer != null) { out.writeInt(1); mWifiMulticastTimer.writeToParcel(out, batteryRealtime); @@ -3266,6 +3373,14 @@ public final class BatteryStatsImpl extends BatteryStats { } else { mWifiScanTimer = null; } + mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED; + for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) { + if (in.readInt() != 0) { + makeWifiBatchedScanBin(i, in); + } else { + mWifiBatchedScanTimer[i] = null; + } + } mWifiMulticastEnabled = false; if (in.readInt() != 0) { mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED, @@ -5463,6 +5578,13 @@ public final class BatteryStatsImpl extends BatteryStats { if (in.readInt() != 0) { u.mWifiScanTimer.readSummaryFromParcelLocked(in); } + u.mWifiBatchedScanBinStarted = Uid.NO_BATCHED_SCAN_STARTED; + for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) { + if (in.readInt() != 0) { + u.makeWifiBatchedScanBin(i, null); + u.mWifiBatchedScanTimer[i].readSummaryFromParcelLocked(in); + } + } u.mWifiMulticastEnabled = false; if (in.readInt() != 0) { u.mWifiMulticastTimer.readSummaryFromParcelLocked(in); @@ -5674,6 +5796,14 @@ public final class BatteryStatsImpl extends BatteryStats { } else { out.writeInt(0); } + for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) { + if (u.mWifiBatchedScanTimer[i] != null) { + out.writeInt(1); + u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); + } else { + out.writeInt(0); + } + } if (u.mWifiMulticastTimer != null) { out.writeInt(1); u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL); @@ -5909,6 +6039,7 @@ public final class BatteryStatsImpl extends BatteryStats { mWifiRunningTimers.clear(); mFullWifiLockTimers.clear(); mWifiScanTimers.clear(); + mWifiBatchedScanTimers.clear(); mWifiMulticastTimers.clear(); sNumSpeedSteps = in.readInt(); diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java index 99a6843..94750d3 100644 --- a/core/java/com/android/internal/os/PowerProfile.java +++ b/core/java/com/android/internal/os/PowerProfile.java @@ -136,6 +136,13 @@ public class PowerProfile { public static final String POWER_CPU_SPEEDS = "cpu.speeds"; /** + * Power consumed by wif batched scaning. Broken down into bins by + * Channels Scanned per Hour. May do 1-720 scans per hour of 1-100 channels + * for a range of 1-72,000. Going logrithmic (1-8, 9-64, 65-512, 513-4096, 4097-)! + */ + public static final String POWER_WIFI_BATCHED_SCAN = "wifi.batchedscan"; + + /** * Battery capacity in milliAmpHour (mAh). */ public static final String POWER_BATTERY_CAPACITY = "battery.capacity"; @@ -171,7 +178,7 @@ public class PowerProfile { String element = parser.getName(); if (element == null) break; - + if (parsingArray && !element.equals(TAG_ARRAYITEM)) { // Finish array sPowerMap.put(arrayName, array.toArray(new Double[array.size()])); diff --git a/core/java/com/android/internal/view/CheckableLinearLayout.java b/core/java/com/android/internal/view/CheckableLinearLayout.java deleted file mode 100644 index 3fb7cec..0000000 --- a/core/java/com/android/internal/view/CheckableLinearLayout.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.view; - -import com.android.internal.R; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.Checkable; -import android.widget.CheckBox; -import android.widget.LinearLayout; - -public class CheckableLinearLayout extends LinearLayout implements Checkable { - private CheckBox mCheckBox; - - public CheckableLinearLayout(Context context) { - super(context); - // TODO Auto-generated constructor stub - } - - public CheckableLinearLayout(Context context, AttributeSet attrs) { - super(context, attrs); - // TODO Auto-generated constructor stub - } - - public CheckableLinearLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - // TODO Auto-generated constructor stub - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mCheckBox = (CheckBox) findViewById(R.id.check); - } - - @Override - public void setChecked(boolean checked) { - mCheckBox.setChecked(checked); - } - - @Override - public boolean isChecked() { - return mCheckBox.isChecked(); - } - - @Override - public void toggle() { - mCheckBox.toggle(); - } -} diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index 5f9d8f2..786f5cf 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -526,7 +526,7 @@ public class ActionBarView extends AbsActionBarView { if (mLogoNavItem != null) { mLogoNavItem.setTitle(title); } - mUpGoerFive.setContentDescription(buildHomeContentDescription()); + updateHomeAccessibility(mUpGoerFive.isEnabled()); } public CharSequence getSubtitle() { @@ -544,7 +544,7 @@ public class ActionBarView extends AbsActionBarView { (!TextUtils.isEmpty(mTitle) || !TextUtils.isEmpty(mSubtitle)); mTitleLayout.setVisibility(visible ? VISIBLE : GONE); } - mUpGoerFive.setContentDescription(buildHomeContentDescription()); + updateHomeAccessibility(mUpGoerFive.isEnabled()); } public void setHomeButtonEnabled(boolean enable) { @@ -681,7 +681,7 @@ public class ActionBarView extends AbsActionBarView { } // Make sure the home button has an accurate content description for accessibility. - updateHomeAccessibility(!mUpGoerFive.isEnabled()); + updateHomeAccessibility(mUpGoerFive.isEnabled()); } public void setIcon(Drawable icon) { @@ -1332,11 +1332,13 @@ public class ActionBarView extends AbsActionBarView { public void setHomeActionContentDescription(CharSequence description) { mHomeDescription = description; + updateHomeAccessibility(mUpGoerFive.isEnabled()); } public void setHomeActionContentDescription(int resId) { mHomeDescriptionRes = resId; mHomeDescription = resId != 0 ? getResources().getText(resId) : null; + updateHomeAccessibility(mUpGoerFive.isEnabled()); } static class SavedState extends BaseSavedState { diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 6ddd3fe..b198937 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1992,6 +1992,14 @@ android:description="@string/permdesc_bindWallpaper" android:protectionLevel="signature|system" /> + <!-- Must be required by a {@link com.android.media.remotedisplay.RemoteDisplayProvider}, + to ensure that only the system can bind to it. + @hide --> + <permission android:name="android.permission.BIND_REMOTE_DISPLAY" + android:label="@string/permlab_bindRemoteDisplay" + android:description="@string/permdesc_bindRemoteDisplay" + android:protectionLevel="signature" /> + <!-- Must be required by device administration receiver, to ensure that only the system can interact with it. --> <permission android:name="android.permission.BIND_DEVICE_ADMIN" @@ -2681,6 +2689,15 @@ <service android:name="android.hardware.location.GeofenceHardwareService" android:permission="android.permission.LOCATION_HARDWARE" android:exported="false" /> + + <service android:name="com.android.internal.backup.LocalTransportService" + android:permission="android.permission.CONFIRM_FULL_BACKUP" + android:exported="false"> + <intent-filter> + <action android:name="android.backup.TRANSPORT_HOST" /> + </intent-filter> + </service> + </application> </manifest> diff --git a/core/res/res/drawable-hdpi/ic_media_group_collapse.png b/core/res/res/drawable-hdpi/ic_media_group_collapse.png Binary files differdeleted file mode 100644 index 89abf2c..0000000 --- a/core/res/res/drawable-hdpi/ic_media_group_collapse.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/ic_media_group_expand.png b/core/res/res/drawable-hdpi/ic_media_group_expand.png Binary files differdeleted file mode 100644 index d9470b2..0000000 --- a/core/res/res/drawable-hdpi/ic_media_group_expand.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_dark.png Binary files differindex b47d666..458a2a6 100644 --- a/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_media_route_disabled_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_media_route_off_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_off_holo_dark.png Binary files differindex 13d803c..c91faa9 100644 --- a/core/res/res/drawable-hdpi/ic_media_route_off_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_media_route_off_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_media_route_off_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_off_holo_light.png Binary files differindex 3ae436b..14c9183 100644 --- a/core/res/res/drawable-hdpi/ic_media_route_off_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_media_route_off_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_dark.png Binary files differindex 24824fc..b388d86 100644 --- a/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_light.png Binary files differindex af3819b..76c1323 100644 --- a/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_media_route_on_0_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_dark.png Binary files differindex 83dc251..fd39f9d 100644 --- a/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_light.png Binary files differindex 8d9d592..c74727a 100644 --- a/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_media_route_on_1_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_dark.png Binary files differindex 1310ec9..826c9ae 100644 --- a/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_light.png Binary files differindex 1705074..d0baec3 100644 --- a/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_media_route_on_2_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_holo_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_holo_dark.png Binary files differindex 7027b88..c60ff59 100644 --- a/core/res/res/drawable-hdpi/ic_media_route_on_holo_dark.png +++ b/core/res/res/drawable-hdpi/ic_media_route_on_holo_dark.png diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_holo_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_holo_light.png Binary files differindex 7027b88..75552cc 100644 --- a/core/res/res/drawable-hdpi/ic_media_route_on_holo_light.png +++ b/core/res/res/drawable-hdpi/ic_media_route_on_holo_light.png diff --git a/core/res/res/drawable-hdpi/ic_notification_cast_0.png b/core/res/res/drawable-hdpi/ic_notification_cast_0.png Binary files differnew file mode 100644 index 0000000..a35f281 --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_notification_cast_0.png diff --git a/core/res/res/drawable-hdpi/ic_notification_cast_1.png b/core/res/res/drawable-hdpi/ic_notification_cast_1.png Binary files differnew file mode 100644 index 0000000..9f6e2ad --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_notification_cast_1.png diff --git a/core/res/res/drawable-hdpi/ic_notification_cast_2.png b/core/res/res/drawable-hdpi/ic_notification_cast_2.png Binary files differnew file mode 100644 index 0000000..737137a --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_notification_cast_2.png diff --git a/core/res/res/drawable-hdpi/ic_notification_cast_on.png b/core/res/res/drawable-hdpi/ic_notification_cast_on.png Binary files differnew file mode 100644 index 0000000..ff2753a --- /dev/null +++ b/core/res/res/drawable-hdpi/ic_notification_cast_on.png diff --git a/core/res/res/drawable-hdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-hdpi/ic_notify_wifidisplay.png Binary files differdeleted file mode 100644 index 35f27df..0000000 --- a/core/res/res/drawable-hdpi/ic_notify_wifidisplay.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/ic_media_group_collapse.png b/core/res/res/drawable-mdpi/ic_media_group_collapse.png Binary files differdeleted file mode 100644 index 34454ac..0000000 --- a/core/res/res/drawable-mdpi/ic_media_group_collapse.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/ic_media_group_expand.png b/core/res/res/drawable-mdpi/ic_media_group_expand.png Binary files differdeleted file mode 100644 index 8ce5a44..0000000 --- a/core/res/res/drawable-mdpi/ic_media_group_expand.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/ic_media_route_off_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_off_holo_dark.png Binary files differindex 6764598..9d92648 100644 --- a/core/res/res/drawable-mdpi/ic_media_route_off_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_media_route_off_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_media_route_off_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_off_holo_light.png Binary files differindex 94e0bb6..3e27fc8 100644 --- a/core/res/res/drawable-mdpi/ic_media_route_off_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_media_route_off_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_dark.png Binary files differindex 5ce2f20..72b9e78 100644 --- a/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_light.png Binary files differindex 5105e90..bd462a2 100644 --- a/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_media_route_on_0_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_dark.png Binary files differindex 68c06ed..0a2cc89 100644 --- a/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_light.png Binary files differindex 6e9b144..d162503 100644 --- a/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_media_route_on_1_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_dark.png Binary files differindex 45dc56f3d..997e32b 100644 --- a/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_light.png Binary files differindex 46e743a..d314967 100644 --- a/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_media_route_on_2_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_holo_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_holo_dark.png Binary files differindex e384691..f15d7a9 100644 --- a/core/res/res/drawable-mdpi/ic_media_route_on_holo_dark.png +++ b/core/res/res/drawable-mdpi/ic_media_route_on_holo_dark.png diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_holo_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_holo_light.png Binary files differindex e384691..26d46f8 100644 --- a/core/res/res/drawable-mdpi/ic_media_route_on_holo_light.png +++ b/core/res/res/drawable-mdpi/ic_media_route_on_holo_light.png diff --git a/core/res/res/drawable-mdpi/ic_notification_cast_0.png b/core/res/res/drawable-mdpi/ic_notification_cast_0.png Binary files differnew file mode 100644 index 0000000..d9cedbd --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_notification_cast_0.png diff --git a/core/res/res/drawable-mdpi/ic_notification_cast_1.png b/core/res/res/drawable-mdpi/ic_notification_cast_1.png Binary files differnew file mode 100644 index 0000000..414c67f --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_notification_cast_1.png diff --git a/core/res/res/drawable-mdpi/ic_notification_cast_2.png b/core/res/res/drawable-mdpi/ic_notification_cast_2.png Binary files differnew file mode 100644 index 0000000..280a888 --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_notification_cast_2.png diff --git a/core/res/res/drawable-mdpi/ic_notification_cast_on.png b/core/res/res/drawable-mdpi/ic_notification_cast_on.png Binary files differnew file mode 100644 index 0000000..ab5f1d7 --- /dev/null +++ b/core/res/res/drawable-mdpi/ic_notification_cast_on.png diff --git a/core/res/res/drawable-mdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-mdpi/ic_notify_wifidisplay.png Binary files differdeleted file mode 100644 index f9c8678..0000000 --- a/core/res/res/drawable-mdpi/ic_notify_wifidisplay.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/ic_media_group_collapse.png b/core/res/res/drawable-xhdpi/ic_media_group_collapse.png Binary files differdeleted file mode 100644 index 2fb7428..0000000 --- a/core/res/res/drawable-xhdpi/ic_media_group_collapse.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/ic_media_group_expand.png b/core/res/res/drawable-xhdpi/ic_media_group_expand.png Binary files differdeleted file mode 100644 index 5755b9d..0000000 --- a/core/res/res/drawable-xhdpi/ic_media_group_expand.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_dark.png Binary files differindex 1d48e12..045eee0 100644 --- a/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_dark.png +++ b/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_light.png Binary files differindex 2c8d1ec..6e14e29 100644 --- a/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_light.png +++ b/core/res/res/drawable-xhdpi/ic_media_route_disabled_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_media_route_off_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_off_holo_dark.png Binary files differindex 00b2043..121bbf6 100644 --- a/core/res/res/drawable-xhdpi/ic_media_route_off_holo_dark.png +++ b/core/res/res/drawable-xhdpi/ic_media_route_off_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_media_route_off_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_off_holo_light.png Binary files differindex ce1d939..468a0c3 100644 --- a/core/res/res/drawable-xhdpi/ic_media_route_off_holo_light.png +++ b/core/res/res/drawable-xhdpi/ic_media_route_off_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_dark.png Binary files differindex 3064b46..414a322 100644 --- a/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_dark.png +++ b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_light.png Binary files differindex 4316686..6088a48 100644 --- a/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_light.png +++ b/core/res/res/drawable-xhdpi/ic_media_route_on_0_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_dark.png Binary files differindex 25c4e31..363d7d4 100644 --- a/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_dark.png +++ b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_light.png Binary files differindex 8e32bd2..edf731e 100644 --- a/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_light.png +++ b/core/res/res/drawable-xhdpi/ic_media_route_on_1_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_dark.png Binary files differindex aeaa78f..85cba7b 100644 --- a/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_dark.png +++ b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_light.png Binary files differindex 85277fa..e65ac31 100644 --- a/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_light.png +++ b/core/res/res/drawable-xhdpi/ic_media_route_on_2_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_holo_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_holo_dark.png Binary files differindex b01dbe8..d8e3e3a 100644 --- a/core/res/res/drawable-xhdpi/ic_media_route_on_holo_dark.png +++ b/core/res/res/drawable-xhdpi/ic_media_route_on_holo_dark.png diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_holo_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_holo_light.png Binary files differindex c19a2ad..562dc9a 100644 --- a/core/res/res/drawable-xhdpi/ic_media_route_on_holo_light.png +++ b/core/res/res/drawable-xhdpi/ic_media_route_on_holo_light.png diff --git a/core/res/res/drawable-xhdpi/ic_notification_cast_0.png b/core/res/res/drawable-xhdpi/ic_notification_cast_0.png Binary files differnew file mode 100644 index 0000000..5fb23a0 --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_notification_cast_0.png diff --git a/core/res/res/drawable-xhdpi/ic_notification_cast_1.png b/core/res/res/drawable-xhdpi/ic_notification_cast_1.png Binary files differnew file mode 100644 index 0000000..f01d17d --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_notification_cast_1.png diff --git a/core/res/res/drawable-xhdpi/ic_notification_cast_2.png b/core/res/res/drawable-xhdpi/ic_notification_cast_2.png Binary files differnew file mode 100644 index 0000000..4f4ba7f --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_notification_cast_2.png diff --git a/core/res/res/drawable-xhdpi/ic_notification_cast_on.png b/core/res/res/drawable-xhdpi/ic_notification_cast_on.png Binary files differnew file mode 100644 index 0000000..38f15dd --- /dev/null +++ b/core/res/res/drawable-xhdpi/ic_notification_cast_on.png diff --git a/core/res/res/drawable-xhdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-xhdpi/ic_notify_wifidisplay.png Binary files differdeleted file mode 100644 index 4cc0ee8..0000000 --- a/core/res/res/drawable-xhdpi/ic_notify_wifidisplay.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_dark.png Binary files differindex 7b0c383..178774c 100644 --- a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_dark.png +++ b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_dark.png diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_light.png Binary files differindex efb624e..2dc2092 100644 --- a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_light.png +++ b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_holo_light.png diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_dark.png Binary files differindex 5ee57e4..592ee8c 100644 --- a/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_dark.png +++ b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_dark.png diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_light.png Binary files differindex 6bc2e4a..f0549e2 100644 --- a/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_light.png +++ b/core/res/res/drawable-xxhdpi/ic_media_route_off_holo_light.png diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_dark.png Binary files differindex c13af9c..91268f5 100644 --- a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_dark.png +++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_dark.png diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_light.png Binary files differindex 744fb42..9d5436f 100644 --- a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_light.png +++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_holo_light.png diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_dark.png Binary files differindex ca4d59c..8e77483 100644 --- a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_dark.png +++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_dark.png diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_light.png Binary files differindex fde5688..f396d22 100644 --- a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_light.png +++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_holo_light.png diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_dark.png Binary files differindex b8715c3..260bab4 100644 --- a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_dark.png +++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_dark.png diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_light.png Binary files differindex 668bb25..2c9fb1d 100644 --- a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_light.png +++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_holo_light.png diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_dark.png Binary files differindex 7f54a62..bdbd59c 100644 --- a/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_dark.png +++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_dark.png diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_light.png Binary files differindex 2df924d..f5c33dd 100644 --- a/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_light.png +++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_holo_light.png diff --git a/core/res/res/drawable-xxhdpi/ic_notification_cast_0.png b/core/res/res/drawable-xxhdpi/ic_notification_cast_0.png Binary files differnew file mode 100644 index 0000000..f5b16ed --- /dev/null +++ b/core/res/res/drawable-xxhdpi/ic_notification_cast_0.png diff --git a/core/res/res/drawable-xxhdpi/ic_notification_cast_1.png b/core/res/res/drawable-xxhdpi/ic_notification_cast_1.png Binary files differnew file mode 100644 index 0000000..22efeec --- /dev/null +++ b/core/res/res/drawable-xxhdpi/ic_notification_cast_1.png diff --git a/core/res/res/drawable-xxhdpi/ic_notification_cast_2.png b/core/res/res/drawable-xxhdpi/ic_notification_cast_2.png Binary files differnew file mode 100644 index 0000000..e24cd97 --- /dev/null +++ b/core/res/res/drawable-xxhdpi/ic_notification_cast_2.png diff --git a/core/res/res/drawable-xxhdpi/ic_notification_cast_on.png b/core/res/res/drawable-xxhdpi/ic_notification_cast_on.png Binary files differnew file mode 100644 index 0000000..da1a627 --- /dev/null +++ b/core/res/res/drawable-xxhdpi/ic_notification_cast_on.png diff --git a/core/res/res/drawable-xxhdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-xxhdpi/ic_notify_wifidisplay.png Binary files differdeleted file mode 100644 index fea4774..0000000 --- a/core/res/res/drawable-xxhdpi/ic_notify_wifidisplay.png +++ /dev/null diff --git a/core/res/res/drawable/ic_notification_cast_connecting.xml b/core/res/res/drawable/ic_notification_cast_connecting.xml new file mode 100644 index 0000000..a390bce --- /dev/null +++ b/core/res/res/drawable/ic_notification_cast_connecting.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright 2013, 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. + */ +--> +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:oneshot="false"> + <item android:drawable="@drawable/ic_notification_cast_0" android:duration="500" /> + <item android:drawable="@drawable/ic_notification_cast_1" android:duration="500" /> + <item android:drawable="@drawable/ic_notification_cast_2" android:duration="500" /> + <item android:drawable="@drawable/ic_notification_cast_1" android:duration="500" /> +</animation-list> diff --git a/core/res/res/layout/immersive_mode_cling.xml b/core/res/res/layout/immersive_mode_cling.xml index f97225e..c0cd93d 100644 --- a/core/res/res/layout/immersive_mode_cling.xml +++ b/core/res/res/layout/immersive_mode_cling.xml @@ -37,8 +37,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/cling_bg" - android:paddingLeft="14dp" - android:paddingRight="14dp" + android:paddingStart="14dp" + android:paddingEnd="14dp" android:paddingTop="24dp" android:paddingBottom="24dp"> <TextView diff --git a/core/res/res/layout/media_route_chooser_dialog.xml b/core/res/res/layout/media_route_chooser_dialog.xml new file mode 100644 index 0000000..d1c6267 --- /dev/null +++ b/core/res/res/layout/media_route_chooser_dialog.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 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. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:divider="?android:attr/dividerHorizontal" + android:showDividers="middle"> + <!-- List of routes. --> + <ListView android:id="@+id/media_route_list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" /> + + <!-- Content to show when list is empty. --> + <LinearLayout android:id="@android:id/empty" + android:layout_width="match_parent" + android:layout_height="64dp" + android:orientation="horizontal" + android:paddingLeft="16dp" + android:paddingRight="16dp" + android:visibility="gone"> + <ProgressBar android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" /> + <TextView android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:paddingLeft="16dp" + android:text="@string/media_route_chooser_searching" /> + </LinearLayout> + + <!-- Settings button. --> + <LinearLayout android:layout_width="match_parent" + android:layout_height="wrap_content" + style="?attr/buttonBarStyle"> + <Button android:id="@+id/media_route_extended_settings_button" + android:layout_width="match_parent" + android:layout_height="match_parent" + style="?attr/buttonBarButtonStyle" + android:gravity="center" + android:text="@string/media_route_chooser_extended_settings" + android:visibility="gone" /> + </LinearLayout> +</LinearLayout> diff --git a/core/res/res/layout/media_route_chooser_layout.xml b/core/res/res/layout/media_route_chooser_layout.xml deleted file mode 100644 index 5fcb8c8..0000000 --- a/core/res/res/layout/media_route_chooser_layout.xml +++ /dev/null @@ -1,48 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:showDividers="middle" - android:divider="?android:attr/dividerHorizontal"> - <LinearLayout android:layout_width="match_parent" - android:layout_height="?android:attr/listPreferredItemHeight" - android:gravity="center_vertical" - android:padding="8dp"> - <ImageView android:id="@+id/volume_icon" - android:layout_width="48dp" - android:layout_height="48dp" - android:src="@android:drawable/ic_audio_vol" - android:gravity="center" - android:scaleType="center" /> - <SeekBar android:id="@+id/volume_slider" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:layout_marginStart="8dp" - android:layout_marginEnd="8dp" /> - <ImageButton android:id="@+id/extended_settings" - android:layout_width="48dp" - android:layout_height="48dp" - android:background="?android:attr/selectableItemBackground" - android:src="@android:drawable/ic_sysbar_quicksettings" - android:visibility="gone" /> - </LinearLayout> - <ListView android:id="@id/list" - android:layout_width="match_parent" - android:layout_height="wrap_content" /> -</LinearLayout> diff --git a/core/res/res/layout/media_route_controller_dialog.xml b/core/res/res/layout/media_route_controller_dialog.xml new file mode 100644 index 0000000..78287e0 --- /dev/null +++ b/core/res/res/layout/media_route_controller_dialog.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 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. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:divider="?android:attr/dividerHorizontal" + android:showDividers="middle"> + <!-- Optional volume slider section. --> + <LinearLayout android:id="@+id/media_route_volume_layout" + android:layout_width="match_parent" + android:layout_height="64dp" + android:gravity="center_vertical" + android:padding="8dp" + android:visibility="gone"> + <ImageView android:layout_width="48dp" + android:layout_height="48dp" + android:src="@drawable/ic_audio_vol" + android:gravity="center" + android:scaleType="center" /> + <SeekBar android:id="@+id/media_route_volume_slider" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" /> + </LinearLayout> + + <!-- Optional content view section. --> + <FrameLayout android:id="@+id/media_route_control_frame" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone" /> + + <!-- Disconnect button. --> + <LinearLayout android:layout_width="match_parent" + android:layout_height="wrap_content" + style="?attr/buttonBarStyle"> + <Button android:id="@+id/media_route_disconnect_button" + android:layout_width="match_parent" + android:layout_height="match_parent" + style="?attr/buttonBarButtonStyle" + android:gravity="center" + android:text="@string/media_route_controller_disconnect" /> + </LinearLayout> +</LinearLayout> diff --git a/core/res/res/layout/media_route_list_item.xml b/core/res/res/layout/media_route_list_item.xml index 423d544..bdca433 100644 --- a/core/res/res/layout/media_route_list_item.xml +++ b/core/res/res/layout/media_route_list_item.xml @@ -20,13 +20,6 @@ android:background="@drawable/item_background_activated_holo_dark" android:gravity="center_vertical"> - <ImageView android:layout_width="56dp" - android:layout_height="56dp" - android:scaleType="center" - android:id="@+id/icon" - android:visibility="gone" - android:duplicateParentState="true" /> - <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" @@ -53,14 +46,4 @@ android:duplicateParentState="true" /> </LinearLayout> - <ImageButton - android:layout_width="56dp" - android:layout_height="56dp" - android:id="@+id/expand_button" - android:background="?android:attr/selectableItemBackground" - android:src="@drawable/ic_media_group_expand" - android:scaleType="center" - android:visibility="gone" - android:duplicateParentState="true" /> - </LinearLayout> diff --git a/core/res/res/layout/media_route_list_item_checkable.xml b/core/res/res/layout/media_route_list_item_checkable.xml deleted file mode 100644 index 5fb82f7..0000000 --- a/core/res/res/layout/media_route_list_item_checkable.xml +++ /dev/null @@ -1,60 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<com.android.internal.view.CheckableLinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="?android:attr/listPreferredItemHeight" - android:background="?android:attr/selectableItemBackground" - android:gravity="center_vertical"> - - <ImageView android:layout_width="56dp" - android:layout_height="56dp" - android:scaleType="center" - android:id="@+id/icon" - android:visibility="gone" /> - - <LinearLayout android:layout_width="0dp" - android:layout_height="match_parent" - android:layout_weight="1" - android:orientation="vertical" - android:gravity="start|center_vertical" - android:paddingStart="?android:attr/listPreferredItemPaddingStart" - android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"> - - <TextView android:id="@android:id/text1" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:singleLine="true" - android:ellipsize="marquee" - android:textAppearance="?android:attr/textAppearanceMedium" /> - - <TextView android:id="@android:id/text2" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:singleLine="true" - android:ellipsize="marquee" - android:textAppearance="?android:attr/textAppearanceSmall" /> - </LinearLayout> - - <CheckBox - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="16dp" - android:id="@+id/check" - android:focusable="false" - android:clickable="false" /> - -</com.android.internal.view.CheckableLinearLayout> diff --git a/core/res/res/layout/media_route_list_item_collapse_group.xml b/core/res/res/layout/media_route_list_item_collapse_group.xml deleted file mode 100644 index 323e24d..0000000 --- a/core/res/res/layout/media_route_list_item_collapse_group.xml +++ /dev/null @@ -1,44 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="?android:attr/selectableItemBackground"> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="?android:attr/listPreferredItemHeightSmall" - android:background="#19ffffff" - android:paddingStart="?android:attr/listPreferredItemPaddingStart" - android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" - android:gravity="center_vertical"> - - <TextView android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:singleLine="true" - android:ellipsize="marquee" - android:text="@string/media_route_chooser_grouping_done" - android:textAppearance="?android:attr/textAppearanceMedium" /> - - <ImageView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:src="@drawable/ic_media_group_collapse" - android:scaleType="center" /> - - </LinearLayout> -</FrameLayout>
\ No newline at end of file diff --git a/core/res/res/layout/media_route_list_item_section_header.xml b/core/res/res/layout/media_route_list_item_section_header.xml deleted file mode 100644 index 949635f..0000000 --- a/core/res/res/layout/media_route_list_item_section_header.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingTop="16dp"> - <TextView - android:id="@android:id/text1" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceSmall" - android:background="#19ffffff" - android:textStyle="bold" - android:textAllCaps="true" - android:gravity="center_vertical" - android:paddingStart="?android:attr/listPreferredItemPaddingStart" - android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" - android:minHeight="24dp" - /> -</FrameLayout> diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index b27ac62..0358de3 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n VPN-diens te bind. Dit moet nooit vir normale programme nodig wees nie."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind aan \'n muurpapier"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n muurpapier te bind. Dit moet nooit vir normale programme nodig wees nie."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"koppel aan \'n afstandskerm"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Dit laat die houer toe om aan die top-koppelvlak van \'n afstandskerm te koppel. Behoort nooit vir gewone programme nodig te wees nie."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind aan \'n legstukdiens"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n legstuk-diens te bind. Dit moet nooit vir normale programme nodig wees nie."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"skakel met \'n toestel-admin"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Stelsel"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-oudio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Draadlose skerm"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Klaar"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Media-uitvoer"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Koppel aan toestel"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Saai skerm uit na toestel"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Soek tans vir toestelle…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Instellings"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Ontkoppel"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Skandeer tans..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Koppel tans..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Beskikbaar"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Oorlegger #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", veilig"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Draadlose skerm is gekoppel"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Hierdie skerm word op \'n ander toestel gewys"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Skerm word tans uitgesaai"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Koppel tans aan <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Skerm word tans uitgesaai"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Gekoppel aan <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Ontkoppel"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Noodoproep"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Het jy die patroon vergeet?"</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 1f9599d..1e320e2 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -269,7 +269,7 @@ <string name="permdesc_sendSms" msgid="7094729298204937667">"መተግበሪያው የኤስ.ኤም.ኤስ. መልዕክቶችን እንዲልክ ይፈቅድለታል። ይህ ያልተጠበቁ ወጪዎችን ሊያስከትል ይችላል። ተንኮል አዘል መተግበሪያዎች ያላንተ ማረጋገጫ መልዕክቶችን በመላክ ገንዘብ ሊያስወጡህ ይችላሉ።"</string> <string name="permlab_sendRespondViaMessageRequest" msgid="8713889105305943200">"የበመልዕክት-በኩል-ምላሽ-ስጥ ክስተቶችን ይላኩ"</string> <string name="permdesc_sendRespondViaMessageRequest" msgid="7107648548468778734">"መተግበሪያው ሌሎች የመልዕክት መላኪያ መተግበሪያዎች ለመጪ ጥሪዎች በመልዕክት-በኩል-ምላሽ-መስጠት ስራን እንዲይዙ ጥያቄዎች እንዲልክላቸው ያስችለዋል።"</string> - <string name="permlab_readSms" msgid="8745086572213270480">"የጽሑፍ መልዕክቶችህን አንብብ (ኤስ.ኤም.ኤስ. ወይም ኤም.ኤም.ኤስ.)"</string> + <string name="permlab_readSms" msgid="8745086572213270480">"የጽሑፍ መልዕክቶችዎን ያንብቡ (ኤስ.ኤም.ኤስ. ወይም ኤም.ኤም.ኤስ.)"</string> <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"መገለጫው በጡባዊ ቱኮህ ወይም በSIM ካርድህ የተከማቹ የኤስ.ኤም.ኤስ. መልእክቶችን እንዲያነብ ይፈቅድለታል። ይህ መተግበሪያው ይዘት ወይም ሚስጥራዊነትን ከግምት ሳያስገባ ሁሉንም የኤስ.ኤም.ኤስ. መልእክቶች እንዲያነብ ይፈቅድለታል።"</string> <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"መገለጫው በስልክህ ወይም በSIM ካርድህ የተከማቹ የኤስ.ኤም.ኤስ. መልእክቶችን እንዲያነብ ይፈቅድለታል። ይህ መተግበሪያው ይዘት ወይም ሚስጥራዊነትን ከግምት ሳያስገባ ሁሉንም የኤስ.ኤም.ኤስ. መልእክቶች እንዲያነብ ይፈቅድለታል።"</string> <string name="permlab_writeSms" msgid="3216950472636214774">"የጽሑፍ መልዕክቶችህን አርትዕ (ኤስ.ኤም.ኤስ. ወይም ኤም.ኤም.ኤስ.)"</string> @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"የVPN ግልጋሎትን ወደ ከፍተኛ-ደረጃ በየነ ገጽ ለማሳር ለመያዣው ይፈቅዳሉ፡፡ለተለመዱ መተግበሪያዎች አያስፈልግም፡፡"</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"በልጣፍ ጠርዝ"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"ያዡ ግቤት ስልቱን ወደ ከፍተኛ-ደረጃ ልጣፍ ለመጠረዝ ይፈቅዳሉ። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ከአንድ የርቀት ማሳያ ጋር ይጠርዛል"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"ያዢው ከአንድ የርቀት ማሳያ ከፍተኛ-ደረጃ በይነገጽ ጋር እንዲጠርዝ ይፈቅድለታል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ወደ ፍርግም አገልግሎት አያይዝ"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ያዡ ግቤት ስልቱን ወደ ከፍተኛ-ደረጃ ፍርግም አገልግሎት ለመጠረዝ ይፈቅዳሉ። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ከመሣሪያ አስተዳደር ጋር ተገናኝ"</string> @@ -498,9 +500,9 @@ <string name="permdesc_mediaContentControl" msgid="1637478200272062">"መተግበሪያው የሚዲያ መልሰህ አጫውትን እንዲቆጣጠር እና የሚዲያ መረጃውን (ርእስ፣ ደራሲ...) እንዲደርስ ይፈቅድለታል።"</string> <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"የድምፅ ቅንብሮችን ለውጥ"</string> <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"መተግበሪያው አንደ የድምጽ መጠን እና ለውጽአት የትኛውን የድምጽ ማጉያ ጥቅም ላይ እንደዋለ የመሳሰሉ ሁለንተናዊ የድምጽ ቅንብሮችን እንዲያስተካክል ይፈቅድለታል።"</string> - <string name="permlab_recordAudio" msgid="3876049771427466323">"ኦዲዮ ቅዳ"</string> + <string name="permlab_recordAudio" msgid="3876049771427466323">"ኦዲዮ ይቅዱ"</string> <string name="permdesc_recordAudio" msgid="4906839301087980680">"መተግበሪያው ድምጽን በማይክሮፎን እንዲቀዳ ይፈቅድለታል። ይህ ፈቃድ መተግበሪያው ያላንተ ማረጋገጫ በማንኛውም ጊዜ ድምጽ እንዲቀዳ ይፈቅድለታል።"</string> - <string name="permlab_camera" msgid="3616391919559751192">"ፎቶዎች እና ቪዲዮዎች አንሳ"</string> + <string name="permlab_camera" msgid="3616391919559751192">"ፎቶዎች እና ቪዲዮዎች ያንሱ"</string> <string name="permdesc_camera" msgid="8497216524735535009">"መተግበሪያው በካሜራው ፎቶዎችንና ቪዲዮዎችን እንዲያነሳ ይፈቅድለታል። ይህ ፈቃድ መተግበሪያው ካሜራውን በማንኛውም ጊዜ ያላንተ ማረጋገጫ እንዲጠቀም ይፈቅድለታል።"</string> <string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"ካሜራው ስራ ላይ ሲሆን የማስተላለፍ አመልካች ኤል ኢ ዲን ያሰናክሉ"</string> <string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"ቀድሞ የተጫነ የስርዓት መተግበሪያ ካሜራውን አመላካች ኤል ኢ ዲ እንዳይጠቀም እንዲያሰናክል ያስችለዋል።"</string> @@ -583,12 +585,12 @@ <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">" የስልኩን ሰዓት መለወጥ ለመተግበሪያው ይፈቅዳሉ።"</string> <string name="permlab_accountManagerService" msgid="4829262349691386986">"እንደ አውርድአዸራጅአገልግሎት"</string> <string name="permdesc_accountManagerService" msgid="1948455552333615954">" ወደ መለያ አረጋጋጮች ጥሪ ለማድረግ ለመተግበሪያ ይፈቅዳሉ።"</string> - <string name="permlab_getAccounts" msgid="1086795467760122114">"መሣሪያው ላይ ያሉ መለያዎችን አግኝ"</string> + <string name="permlab_getAccounts" msgid="1086795467760122114">"መሣሪያው ላይ ያሉ መለያዎችን ያግኙ"</string> <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"መተግበሪያው በጡባዊ ተኮው የሚታወቁትን መለያዎች ዝርዝር እንዲያገኝ ይፈቅድለታል። ይህ በጫንዋቸው ማናቸውም መተግበሪያዎች የተፈጠሩ መለያዎችን ሊያጠቃልል ይችላል።"</string> <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"መተግበሪያው በስልኩ የሚታወቁትን መለያዎች ዝርዝር እንዲያገኝ ይፈቅድለታል። ይህ በጫንዋቸው ማናቸውም መተግበሪያዎች የተፈጠሩ መለያዎችን ሊያጠቃልል ይችላል።"</string> <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"መለያዎችን ፍጠርና የይለፍ ቃላትን አስቀምጥ"</string> <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"የመለያ አረጋጋጭ መለያ መናጅ ችሎታን ለመጠቀም፣ መለያ መፍጠር እና የይለፍ ቃሎችን ለማግኘት እና ለማቀናጀት አክሎ ለመተግበሪያው ይፈቅዳሉ ።"</string> - <string name="permlab_manageAccounts" msgid="4983126304757177305">"መለያዎችን አክል ወይም አስወግድ"</string> + <string name="permlab_manageAccounts" msgid="4983126304757177305">"መለያዎችን ያክሉ ወይም ያስወግዱ"</string> <string name="permdesc_manageAccounts" msgid="8698295625488292506">"መለያዎችን እንደ ማከል እና ማስወገድ ክወናዎችን እና የይለፍ ቃልን መሰረዝ ለማከናወን ለመተግበሪያው ይፈቅዳሉ፡፡"</string> <string name="permlab_useCredentials" msgid="235481396163877642">"በመሣሪያው ላይ ያሉ መለያዎችን ይጠቀሙ"</string> <string name="permdesc_useCredentials" msgid="7984227147403346422">"የማረጋገጫ የምስጋና የምስክር ወረቀትን ለመጠየቅ ለመተግበሪያው ይፈቅዳሉ፡፡"</string> @@ -643,7 +645,7 @@ <string name="permdesc_readDictionary" msgid="659614600338904243">"መተግበሪያው ተጠቃሚው በተጠቃሚው መዝገበ-ቃላት አከማችቷቸው ሊሆኑ የሚችሉ ሁሉንም ቃላት፣ ስሞችና ሐረጋት እንዲያነባቸው ይፈቅድለታል።"</string> <string name="permlab_writeDictionary" msgid="2183110402314441106">"በተጠቃሚ በተገለጸ መዝገበ ቃላት ላይ ቃላትን ያክላል"</string> <string name="permdesc_writeDictionary" msgid="8185385716255065291">"በተጠቃሚ መዝገበ ቃላት ውስጥ አዲስ ቃል እንዲጽፍ ለመተግበሪያው ይፈቅዳሉ፡፡"</string> - <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"የUSB ማከማቻህን ይዘቶች አንብብ"</string> + <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"የUSB ማከማቻዎን ይዘቶች ያንብቡ"</string> <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"የSD ካርድህን ይዘቶች አንብብ"</string> <string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"መተግበሪያው የእርስዎ USB ማከማቻ ይዘቶችን እንዲያነብ ያስችለዋል።"</string> <string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"መተግበሪያው የእርስዎ SD ካርድ ይዘቶችን እንዲያነብ ያስችለዋል።"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"ስርዓት"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"የብሉቱዝ ድምጽ"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"ገመድ አልባ ማሳያ"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"ተከናውኗል"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"የሚዲያ ውጽዓት"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"ከመሳሪያ ጋር ያገናኙ"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ማያ ገጽን ወደ መሣሪያ ይውሰዱ"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"መሳሪያዎችን በመፈለግ ላይ…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"ቅንብሮች"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"ግንኙነት አቋርጥ"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"በመቃኘት ላይ..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"በማገናኘት ላይ..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"የሚገኙ"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"ተደራቢ #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>፦ <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>፣ <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">"፣ የተጠበቀ"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"ገመድ አልባ ማሳያ ተገናኝቷል"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"ይህ ማያ ገጽ በሌላ መሣሪያ ላይ እያሳየ ነው"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"ማያ ገጽን በመውሰድ ላይ"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"ከ<xliff:g id="NAME">%1$s</xliff:g> ጋር በመገናኘት ላይ"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"ማያ ገጽን በመውሰድ ላይ"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"ከ<xliff:g id="NAME">%1$s</xliff:g> ጋር ተገናኝቷል"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"ግንኙነት አቋርጥ"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"የአደጋ ጊዜ ጥሪ"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"ስርዓተ ጥለቱን እርሳ"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index ab03375..18296ea 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لخدمة الشبكة الظاهرية الخاصة (VPN). لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"الالتزام بخلفية ما"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"للسماح للمالك بالالتزام بواجهة المستوى العلوي للخلفية. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"الربط بالشاشة عن بُعد"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"للسماح للمالك بالالتزام بواجهة المستوى العلوي للعرض عن بُعد. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"الالتزام بخدمة أداة"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لخدمة الأداة. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"التفاعل مع مشرف الجهاز"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"النظام"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"صوت بلوتوث"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"عرض شاشة لاسلكي"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"تم"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"المنفذ الإعلامي"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"الاتصال بجهاز"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"بث الشاشة على الجهاز"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"جارٍ البحث عن الأجهزة…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"الإعدادات"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"قطع الاتصال"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"جارٍ الفحص..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"جارٍ الاتصال..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"متاح"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"المركب #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>، <xliff:g id="DPI">%4$d</xliff:g> نقطة لكل بوصة"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">"آمن"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"تم التوصيل بشاشة لاسلكية"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"يتم عرض هذه الشاشة على جهاز آخر"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"جارٍ بث الشاشة"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"جارٍ الاتصال بـ <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"جارٍ بث الشاشة"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"متصل بـ <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"قطع الاتصال"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"الاتصال بالطوارئ"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"نسيت النقش"</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index 00a77a3..a0dd5d8 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -396,6 +396,10 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Дазваляе ўладальніку звязвацца з інтэрфейсам службы VPN вышэйшага ўзроўню. Не патрэбна для звычайных прыкладанняў."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"прывязаць да шпалер"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Дазваляе ўладальніку ўсталёўваць прывязку да інтэрфейсу шпалер верхняга ўзроўню. Не патрабуецца для звычайных прыкладанняў."</string> + <!-- no translation found for permlab_bindRemoteDisplay (1782923938029941960) --> + <skip /> + <!-- no translation found for permdesc_bindRemoteDisplay (1261242718727295981) --> + <skip /> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"прывязаць да службы віджэту"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Дазваляе ўладальніку прывязвацца да інтэрфейсу верхняга ўзроўню службы віджэта. Не патрабуецца для звычайных прыкладанняў."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"узаемадзейнічаць з адміністратарам прылады"</string> @@ -1536,8 +1540,15 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Сістэма"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-аўдыё"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Бесправадны дысплей"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Гатова"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Мультымедыйны выхад"</string> + <!-- no translation found for media_route_chooser_title (1751618554539087622) --> + <skip /> + <!-- no translation found for media_route_chooser_searching (4776236202610828706) --> + <skip /> + <!-- no translation found for media_route_chooser_extended_settings (87015534236701604) --> + <skip /> + <!-- no translation found for media_route_controller_disconnect (8966120286374158649) --> + <skip /> <string name="media_route_status_scanning" msgid="7279908761758293783">"Сканiраванне..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Падключэнне..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Даступна"</string> @@ -1550,8 +1561,14 @@ <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> кр. на цалю"</string> <!-- no translation found for display_manager_overlay_display_secure_suffix (6022119702628572080) --> <skip /> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Падключаны бесправадны дысплей"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Гэты экран паказваецца на іншай прыладзе"</string> + <!-- no translation found for wifi_display_notification_connecting_title (9102788196896266990) --> + <skip /> + <!-- no translation found for wifi_display_notification_connecting_message (5837350993752841389) --> + <skip /> + <!-- no translation found for wifi_display_notification_connected_title (4118323329495921271) --> + <skip /> + <!-- no translation found for wifi_display_notification_connected_message (2587209325701109715) --> + <skip /> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Адключыць"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Экстранны выклік"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Забылі ключ"</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index d16796e..0d1cdaf 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на услуга за VPN. Нормалните приложения би трябвало никога да не се нуждаят от това."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"обвързване с тапет"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на тапет. Нормалните приложения би трябвало никога да не се нуждаят от това."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"свързване с отдалечен екран"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Разрешава на притежателя да се свърже с интерфейса от първо ниво на отдалечен екран. Нормалните приложения би трябвало никога да не се нуждаят от това."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"обвързване с услуга за приспособления"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на услуга за приспособления. Нормалните приложения би трябвало никога да не се нуждаят от това."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"взаимодействие с администратор на устройството"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Система"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Звук през Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Безжичен дисплей"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Изходяща мултимедия"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Свързване с устройство"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Екран за предаване към устройството"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Търсят се устройства…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Настройки"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Прекратяване на връзката"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Сканира се..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Установява се връзка..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Налице"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Наслагване №<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"„<xliff:g id="NAME">%1$s</xliff:g>“: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", защитено"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Безжичният дисплей е свързан"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Този екран се показва на друго устройство"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Екранът се предава"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Установява се връзка с/ъс „<xliff:g id="NAME">%1$s</xliff:g>“"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Екранът се предава"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Установена е връзка с/ъс „<xliff:g id="NAME">%1$s</xliff:g>“"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Прекратяване на връзката"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Спешно обаждане"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Забравена фигура"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index 65416f1..e0d07bf 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permet que el titular vinculi a la interfície de nivell superior d\'un servei de VPN. No s\'hauria de necessitar mai per a les aplicacions normals."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"enllaça amb un fons de pantalla"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permet que el titular vinculi a la interfície de nivell superior d\'un fons de pantalla. No s\'hauria de necessitar mai per a les aplicacions normals."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"vincula a una pantalla remota"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permet que el titular es vinculi a la interfície de nivell superior d\'una pantalla remota. No s\'hauria de necessitar mai per a les aplicacions normals."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincula a un servei de widget"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permet que el titular vinculi a la interfície de nivell superior d\'un servei de widget. No s\'hauria de necessitar mai per a les aplicacions normals."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar amb un administrador del dispositiu"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Àudio per Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Pantalla sense fil"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fet"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Sortida de contingut multimèdia"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Connexió al dispositiu"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Emissió de pantalla al dispositiu"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"S\'estan cercant dispositius…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Configuració"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Desconnecta"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"S\'està cercant…"</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"S\'està connectant..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Disponible"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Superposa #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", segur"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"La pantalla sense fil està connectada"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Aquesta pantalla es mostra en un altre dispositiu"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Emissió de pantalla"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"S\'està connectant a <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Emissió de pantalla"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Connectat a <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Desconnecta"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Trucada d\'emergència"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Patró oblidat"</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index f4cb4d0..14d6dd5 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Umožňuje držiteli navázat se na nejvyšší úroveň služby VPN. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"vazba na tapetu"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Umožňuje držiteli navázat se na nejvyšší úroveň rozhraní tapety. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"připojit se ke vzdálenému displeji"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Umožňuje držiteli připojit se k vysokoúrovňovému rozhraní vzdáleného displeje. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"navázat se na službu widgetu"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Umožňuje držiteli navázat se na nejvyšší úroveň služby widgetu. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"komunikovat se správcem zařízení"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Systém"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth Audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Bezdrátový displej"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Hotovo"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Výstup médií"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Připojení k zařízení"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Odesílání obsahu obrazovky do zařízení"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Vyhledávání zařízení…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Nastavení"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Odpojit"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Vyhledávání…"</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Připojování…"</string> <string name="media_route_status_available" msgid="6983258067194649391">"Dostupná"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Překryvná vrstva č. <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", zabezpečené"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Bezdrátový displej je připojen"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Tato obrazovka se zobrazuje v jiném zařízení"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Odesílání obsahu obrazovky"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Připojování k obrazovce <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Odesílání obsahu obrazovky"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Připojeno k obrazovce <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Odpojit"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Tísňové volání"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Zapomenuté gesto"</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 997837a..0219a0f 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Tillader, at brugeren forpligter sig til en VPN-tjenestes grænseflade på øverste niveau. Bør aldrig være nødvendigt i almindelige apps."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"forpligt til et tapet"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Tillader, at indehaveren kan binde en baggrunds grænseflade på øverste niveau. Dette bør aldrig være nødvendigt for almindelige apps."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bind til en ekstern skærm"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Tillader, at brugeren kan foretage en binding til grænsefladens øverste niveau på en ekstern skærm. Bør aldrig være nødvendigt til almindelige apps."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"forpligt til en widgettjeneste"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Tillader, at brugeren kan forpligte sig til en grænseflade for en widgettjeneste på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunikere med en enhedsadministrator"</string> @@ -1119,7 +1121,7 @@ <string name="loading" msgid="7933681260296021180">"Indlæser…"</string> <string name="capital_on" msgid="1544682755514494298">"TIL"</string> <string name="capital_off" msgid="6815870386972805832">"FRA"</string> - <string name="whichApplication" msgid="4533185947064773386">"Fuldfør handling ved hjælp af"</string> + <string name="whichApplication" msgid="4533185947064773386">"Brug"</string> <string name="whichHomeApplication" msgid="4616420172727326782">"Vælg en startsideapp"</string> <string name="alwaysUse" msgid="4583018368000610438">"Brug som standard til denne handling."</string> <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Ryd standard i Systemindstillinger > Apps > Downloadet."</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-lyd"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Trådløs skærm"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Udfør"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Medieudgang"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Opret forbindelse til enheden"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Send skærm til enhed"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Søger efter enheder…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Indstillinger"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Afbryd forbindelsen"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Søger..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Opretter forbindelse..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Tilgængelig"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlejring nr. <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", sikker"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Der er tilsluttet en trådløs skærm"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Denne skærm vises på en anden enhed"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Skærm sendes"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Der oprettes forbindelse til <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Skærm sendes"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Forbundet til <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Afbryd forbindelsen"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Nødopkald"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Glemt mønster"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 4f40d72..34f28fc 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Ermöglicht dem Halter, sich an die Oberfläche eines VPN-Dienstes auf oberster Ebene zu binden. Sollte nie für normale Apps benötigt werden."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"An einen Hintergrund binden"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Ermöglicht dem Halter, sich an die Oberfläche eines Hintergrunds auf oberster Ebene zu binden. Sollte nie für normale Apps benötigt werden."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"An Remote-Display binden"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Ermöglicht dem Halter, sich an die Oberfläche eines Remote-Displays auf oberster Ebene zu binden. Sollte für normale Apps nie benötigt werden."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"An einen Widget-Dienst binden"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ermöglicht dem Halter, sich an die Oberfläche eines Widget-Dienstes auf oberster Ebene zu binden. Sollte nie für normale Apps benötigt werden."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"Interaktion mit einem Geräteadministrator"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-Audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Kabellose Übertragung (WiDi)"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fertig"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Medienausgabe"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Mit Gerät verbinden"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Bildschirm auf Gerät übertragen"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Geräte werden gesucht…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Einstellungen"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Verbindung trennen"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Wird gescannt..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Verbindung wird hergestellt..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Verfügbar"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay-Nr. <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", sicher"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Kabellose Übertragung (WiDi) ist aktiviert."</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Dieser Bildschirm wird auf einem anderen Gerät angezeigt."</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Bildschirm wird übertragen"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Verbindung mit <xliff:g id="NAME">%1$s</xliff:g> wird hergestellt."</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Bildschirm wird übertragen"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Verbunden mit <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Verbindung trennen"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Notruf"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Muster vergessen"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 6a34a6a..ee98ceb 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας Vpn. Δεν απαιτείται για κανονικές εφαρμογές."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"δέσμευση σε ταπετσαρία"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας ταπετσαρίας. Δεν απαιτείται για συνήθεις εφαρμογές."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"μεταφορά σε μια απομακρυσμένη οθόνη"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας απομακρυσμένης οθόνης. Δεν απαιτείται ποτέ για κανονικές εφαρμογές."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"δέσμευση σε υπηρεσία γραφικών στοιχείων"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας γραφικών στοιχείων. Δεν απαιτείται για κανονικές εφαρμογές."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"επικοινωνία με έναν διαχειριστή συσκευής"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Σύστημα"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Ήχος Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Ασύρματη οθόνη"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Τέλος"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Έξοδος μέσων"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Σύνδεση με τη συσκευή"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Μετάδοση οθόνης σε συσκευή"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Αναζήτηση συσκευών…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Ρυθμίσεις"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Αποσύνδεση"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Σάρωση…"</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Σύνδεση…"</string> <string name="media_route_status_available" msgid="6983258067194649391">"Διαθέσιμη"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Επικάλυψη #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", ασφαλές"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Έχει συνδεθεί ασύρματη οθόνη"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Αυτή η οθόνη εμφανίζεται σε μια άλλη συσκευή"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Μετάδοση οθόνης"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Γίενται σύνδεση με το <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Μετάδοση οθόνης"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Συνδέθηκε με το <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Αποσύνδεση"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Κλήσεις επείγουσας ανάγκης"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Ξεχάσατε το μοτίβο"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index b706ee8..d2c53cc 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Allows the holder to bind to the top-level interface of a Vpn service. Should never be needed for normal apps."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind to wallpaper"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Allows the holder to bind to the top-level interface of wallpaper. Should never be needed for normal applications."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bind to a remote display"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Allows the holder to bind to the top-level interface of a remote display. Should never be needed for normal apps."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind to a widget service"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Allows the holder to bind to the top-level interface of a widget service. Should never be needed for normal apps."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interact with device admin"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Wireless display"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Done"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Media output"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Connect to device"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Cast screen to device"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Searching for devices…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Settings"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Disconnect"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Scanning..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Connecting..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Available"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", secure"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Wireless display is connected"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"This screen is showing on another device"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Casting screen"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Connecting to <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Casting screen"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Connected to <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Disconnect"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Emergency call"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Forgot Pattern"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index b706ee8..d2c53cc 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Allows the holder to bind to the top-level interface of a Vpn service. Should never be needed for normal apps."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind to wallpaper"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Allows the holder to bind to the top-level interface of wallpaper. Should never be needed for normal applications."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bind to a remote display"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Allows the holder to bind to the top-level interface of a remote display. Should never be needed for normal apps."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind to a widget service"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Allows the holder to bind to the top-level interface of a widget service. Should never be needed for normal apps."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interact with device admin"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Wireless display"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Done"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Media output"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Connect to device"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Cast screen to device"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Searching for devices…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Settings"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Disconnect"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Scanning..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Connecting..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Available"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", secure"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Wireless display is connected"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"This screen is showing on another device"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Casting screen"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Connecting to <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Casting screen"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Connected to <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Disconnect"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Emergency call"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Forgot Pattern"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 165b6a6..114f6f5 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite al titular vincularse a la interfaz de nivel superior de un servicio de VPN. Las aplicaciones normales no deberían necesitar este permiso."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"vincular a un fondo de pantalla"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite al propietario vincularse a la interfaz de nivel superior de un fondo de pantalla. Las aplicaciones normales no deben utilizar este permiso."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"vincular a una pantalla remota"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite al propietario vincularse a la interfaz de nivel superior de una pantalla remota. Las aplicaciones normales no deberían necesitar este permiso."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincular a un servicio de widget"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite al propietario vincularse a la interfaz de nivel superior del servicio de widget. Las aplicaciones normales no deberían necesitar este permiso."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar con un administrador de dispositivos"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Pantalla inalámbrica"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Listo"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Salida multimedia"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Conectar al dispositivo"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Transmitir pantalla a dispositivo"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Buscando dispositivos…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Configuración"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Desconectar"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Examinando..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Conectando..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Disponible"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Superposición #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> ppp"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", segura"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Se conectó la pantalla inalámbrica"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Esta pantalla se muestra en otro dispositivo."</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Transmitiendo pantalla"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Estableciendo conexión con <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Transmitiendo pantalla"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Se estableció conexión con <xliff:g id="NAME">%1$s</xliff:g>."</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Desconectar"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Realizar llamada de emergencia"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"¿Olvidaste el patrón?"</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index c38a075..f758989 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite enlazar con la interfaz de nivel superior de un servicio de VPN. Las aplicaciones normales no deberían necesitar este permiso."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"enlazar con un fondo de pantalla"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite enlazar con la interfaz de nivel superior de un fondo de pantalla. Las aplicaciones normales no deberían necesitar este permiso."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"enlazar a una pantalla remota"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite enlazar con la interfaz de nivel superior de una pantalla remota. Las aplicaciones normales no deberían necesitar este permiso."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"enlazar con un servicio de widget"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite enlazar con la interfaz de nivel superior de un servicio de widget. Las aplicaciones normales no deberían necesitar este permiso."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar con el administrador de un dispositivo"</string> @@ -788,7 +790,7 @@ <string name="imProtocolYahoo" msgid="8271439408469021273">"Yahoo!"</string> <string name="imProtocolSkype" msgid="9019296744622832951">"Skype"</string> <string name="imProtocolQq" msgid="8887484379494111884">"QQ"</string> - <string name="imProtocolGoogleTalk" msgid="493902321140277304">"Conversaciones"</string> + <string name="imProtocolGoogleTalk" msgid="493902321140277304">"Hangouts"</string> <string name="imProtocolIcq" msgid="1574870433606517315">"ICQ"</string> <string name="imProtocolJabber" msgid="2279917630875771722">"Jabber"</string> <string name="imProtocolNetMeeting" msgid="8287625655986827971">"NetMeeting"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Pantalla inalámbrica"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fin"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Salida multimedia"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Conectar a dispositivo"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Enviar pantalla a dispositivo"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Buscando dispositivos…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Ajustes"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Desconectar"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Analizando..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Conectando..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Disponible"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Superposición #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", seguro"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Pantalla inalámbrica conectada"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Esta pantalla se muestra en otro dispositivo."</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Enviando pantalla"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Conectando a <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Enviando pantalla"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Conectado a <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Desconectar"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Llamada de emergencia"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"¿Has olvidado el patrón?"</string> diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml index 5f05ac2..39523ef 100644 --- a/core/res/res/values-et-rEE/strings.xml +++ b/core/res/res/values-et-rEE/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Võimaldab omanikul siduda VPN-teenuse ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"taustapildiga sidumine"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Lubab omanikul siduda taustapildi ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"kaugekraaniga sidumine"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Lubab omanikul siduda rakenduse kaugekraani ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vidinateenusega sidumine"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lubab omanikul siduda vidina teenuse ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"seadme administraatoriga suhtlemine"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Süsteem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-heli"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Juhtmeta ekraan"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Valmis"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Meediaväljund"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Seadmega ühendamine"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Ekraanikuva ülekandmine seadmesse"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Seadmete otsimine …"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Seaded"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Katkesta ühendus"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Skaneering ..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Ühendan..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Saadaval"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Ülekate nr .<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", turvaline"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Juhtmeta ekraaniühendus on loodud"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Ekraan on näha teises seadmes"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Ekraanikuva ülekandmine"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Ühendamine ekraaniga <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Ekraanikuva ülekandmine"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Ühendatud ekraaniga <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Katkesta ühendus"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Hädaabikõne"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Unustasin mustri"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index baa11fa..93a8eec 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"به دارنده اجازه میدهد که به رابط سطح بالای سرویس Vpn متصل شود. هرگز برای برنامههای معمولی مورد نیاز نیست."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"پیوند شده به تصویر زمینه"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"به دارنده اجازه میدهد تا به رابط سطح بالای تصویر زمینه متصل شود. برنامههای معمولی هرگز به این ویژگی نیاز ندارند."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"اتصال به نمایشگر راه دور"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"به دارنده امکان میدهد تا به رابط سطح بالای نمایشگر راه دور وصل شود. نباید هرگز برای برنامههای عادی لازم باشد."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"اتصال به یک سرویس ابزارک"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"به دارنده اجازه میدهد که به رابط سطح بالای سرویس ابزارک متصل شود. هرگز برای برنامههای معمولی مورد نیاز نیست."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"تعامل با یک سرپرست دستگاه"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"سیستم"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"بلوتوثهای صوتی"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"صفحه نمایش بیسیم"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"انجام شد"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"خروجی رسانه"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"برقراری ارتباط با دستگاه"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"فرستادن صفحه نمایش به دستگاه"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"در حال جستجو برای دستگاهها..."</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"تنظیمات"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"قطع ارتباط"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"در حال اسکن کردن…"</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"درحال اتصال…"</string> <string name="media_route_status_available" msgid="6983258067194649391">"در دسترس"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"همپوشانی #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">"، امن"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"نمایشگر بیسیم متصل است"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"این صفحه در حال نمایش در دستگاه دیگری است"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"درحال فرستادن صفحه نمایش"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"درحال اتصال به <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"درحال فرستادن صفحه نمایش"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"به <xliff:g id="NAME">%1$s</xliff:g> متصل شد"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"قطع اتصال"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"تماس اضطراری"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"الگو را فراموش کردهاید"</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 3718ccc..e4d4e3e 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Antaa sovelluksen sitoutua VPN-palvelun ylemmän tason käyttöliittymään. Ei tavallisten sovellusten käyttöön."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"sido taustakuvaan"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Antaa sovelluksen sitoutua taustakuvan ylätason käyttöliittymään. Ei tavallisten sovellusten käyttöön."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"etänäyttöön sitoutuminen"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Antaa sovelluksen sitoutua etänäytön ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"sitoudu widget-palveluun"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Antaa sovelluksen sitoutua widget-palvelun ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunikoi laitteen järjestelmänvalvojan kanssa"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Järjestelmä"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-ääni"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Langaton näyttö"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Valmis"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Median äänentoisto"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Yhdistä laitteeseen"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Lähetä näyttö laitteeseen"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Etsitään laitteita…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Asetukset"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Katkaise yhteys"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Etsitään..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Yhdistetään..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Käytettävissä"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Peittokuva # <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", suojattu"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Langaton näyttö on yhdistetty"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Tämä ruutu näkyy toisella laitteella"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Lähetetään näyttöä"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Yhdistetään näyttöön <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Lähetetään näyttöä"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Yhdistetty näyttöön <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Katkaise yhteys"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Hätäpuhelu"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Unohtunut kuvio"</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index bbfaad7..7c11f9a 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service RPV. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"se fixer à un fond d\'écran"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un fond d\'écran. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"lier à un écran distant"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un écran distant. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"s\'associer à un service de widget"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service de widget. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir avec l\'administrateur d\'un périphérique"</string> @@ -788,7 +790,7 @@ <string name="imProtocolYahoo" msgid="8271439408469021273">"Yahoo"</string> <string name="imProtocolSkype" msgid="9019296744622832951">"Skype"</string> <string name="imProtocolQq" msgid="8887484379494111884">"QQ"</string> - <string name="imProtocolGoogleTalk" msgid="493902321140277304">"Conversations"</string> + <string name="imProtocolGoogleTalk" msgid="493902321140277304">"Hangouts"</string> <string name="imProtocolIcq" msgid="1574870433606517315">"ICQ"</string> <string name="imProtocolJabber" msgid="2279917630875771722">"Jabber"</string> <string name="imProtocolNetMeeting" msgid="8287625655986827971">"NetMeeting"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Système"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Affichage sans fil"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Terminé"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Sortie multimédia"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Connexion à l\'appareil"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Diffuser l\'écran sur l\'appareil"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Recherche d\'appareils en cours…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Paramètres"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Déconnecter"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Analyse en cours..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Connexion en cours..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Disponible"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Superposition n° <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g> : <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> ppp"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", sécurisé"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"L\'affichage sans fil est connecté."</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Cet écran s\'affiche sur un autre appareil."</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Connexion à l\'écran en cours"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Connexion au réseau <xliff:g id="NAME">%1$s</xliff:g> en cours…"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Diffusion de l\'écran en cours"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Connecté à <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Déconnecter"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Appel d\'urgence"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"J\'ai oublié le schéma"</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index a6d7687..04a55f2 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service VPN. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"Se fixer sur un fond d\'écran"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un fond d\'écran. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"s\'associer à un écran à distance"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permettre à l\'application autorisée de s\'associer à l\'interface de niveau supérieur d\'un écran à distance. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"associer à un service widget"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service widget. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir avec l\'administrateur du périphérique"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Système"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Affichage sans fil"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"OK"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Sortie multimédia"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Connexion à l\'appareil"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Diffuser l\'écran sur l\'appareil"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Recherche d\'appareils en cours…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Paramètres"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Déconnecter"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Analyse en cours..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Connexion en cours..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Disponible"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Superposition n° <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g> : <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", sécurisé"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"L\'affichage sans fil est connecté."</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Cet écran s\'affiche sur un autre appareil."</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Diffusion de l\'écran en cours"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Connexion à <xliff:g id="NAME">%1$s</xliff:g> en cours…"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Diffusion de l\'écran en cours"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Connecté à <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Déconnecter"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Appel d\'urgence"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"J\'ai oublié le schéma"</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 59ac55c..2650108 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"धारक को किसी Vpn सेवा के शीर्ष-स्तर इंटरफ़ेस से आबद्ध होने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"वॉलपेपर से आबद्ध करें"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"धारक को किसी वॉलपेपर के शीर्ष-स्तर इंटरफ़ेस से आबद्ध होने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"रिमोट डिस्प्ले से आबद्ध करें"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"धारक को किसी रिमोट डिस्प्ले के शीर्ष-स्तरीय इंटरफ़ेस से आबद्ध होने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"किसी विजेट सेवा से आबद्ध करें"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"धारक को किसी विजेट सेवा के शीर्ष-स्तर इंटरफ़ेस से आबद्ध होने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"किसी उपकरण व्यवस्थापक के साथ सहभागिता करें"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"सिस्टम"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth ऑडियो"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"वायरलेस प्रदर्शन"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"पूर्ण"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"मीडिया आउटपुट"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"उपकरण से कनेक्ट करें"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"स्क्रीन को उपकरण में कास्ट करें"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"उपकरण खोजे जा रहे हैं…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"सेटिंग"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"डिस्कनेक्ट करें"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"स्कैन कर रहा है..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"कनेक्ट हो रहा है..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"उपलब्ध"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"ओवरले #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", सुरक्षित"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"वायरलेस डिस्प्ले कनेक्ट है"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"यह स्क्रीन अन्य उपकरण पर दिखाई दे रही है"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"स्क्रीन कास्ट हो रही है"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"<xliff:g id="NAME">%1$s</xliff:g> से कनेक्ट हो रहा है"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"स्क्रीन कास्ट हो रही है"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"<xliff:g id="NAME">%1$s</xliff:g> से कनेक्ट है"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"डिस्कनेक्ट करें"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"आपातकालीन कॉल"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"आकार भूल गए"</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 2b04e02..829c03d 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Nositelju omogućuje vezanje uz sučelje najviše razine VPN usluge. Ne bi smjelo biti potrebno za normalne aplikacije."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"povezano s pozadinskom slikom"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Nositelju omogućuje povezivanje sa sučeljem pozadinske slike najviše razine. Ne bi smjelo biti potrebno za normalne aplikacije."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"vezanje uz udaljeni zaslon"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Nositelju omogućuje vezanje uza sučelje najviše razine udaljenog zaslona. Ne bi smjelo biti potrebno za normalne aplikacije."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vezanje na uslugu widgeta"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Nositelju omogućuje vezanje uz sučelje najviše razine usluge widgeta. Ne bi smjelo biti potrebno za normalne aplikacije."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interakcija s administratorom uređaja"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sustav"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth zvuk"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Bežični prikaz"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gotovo"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Medijski izlaz"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Povezivanje s uređajem"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Emitiranje zaslona na uređaj"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Traženje uređaja…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Postavke"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Prekini vezu"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Skeniranje..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Povezivanje..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Dostupno"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Preklapanje br. <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", sigurno"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Bežični je prikaz povezan"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Ovaj se zaslon prikazuje na nekom drugom uređaju"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Emitiranje zaslona"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Povezivanje sa zaslonom <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Emitiranje zaslona"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Povezan sa zaslonom <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Isključi"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Hitan poziv"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Zaboravili ste obrazac"</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 71f6bdc..4c9f400 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Lehetővé teszi a használó számára, hogy csatlakozzon egy VPN-szolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szüksége."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"összekapcsolás háttérképpel"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Lehetővé teszi, hogy a tulajdonos kötelezővé tegye egy háttérkép legfelső szintű felületét. A normál alkalmazásoknak erre soha nincs szüksége."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"csatlakozás egy távoli kijelzőhöz"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Lehetővé teszi a használó számára, hogy csatlakozzon egy távoli kijelző legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"csatlakozás modulszolgáltatáshoz"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lehetővé teszi a használó számára, hogy csatlakozzon egy modulszolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szüksége."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"az eszközkezelő használata"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Rendszer"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth hang"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Vezeték nélküli kijelző"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Kész"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Médiakimenet"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Csatlakozás adott eszközhöz"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Képernyő átküldése az eszközre"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Eszközkeresés…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Beállítások"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Leválasztás"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Keresés..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Kapcsolódás..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Elérhető"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"<xliff:g id="ID">%1$d</xliff:g>. fedvény"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> képpont"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", biztonságos"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Vezeték nélküli kijelző csatlakoztatva"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Ez a kijelző megjelenítést végez egy másik eszközön"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Képernyő átküldése…"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Csatlakozás a következőhöz: <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Képernyő átküldése…"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Csatlakozva a következőhöz: <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Szétkapcsol"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Segélyhívás"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Elfelejtett minta"</string> diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml index f5ed539..85eedba 100644 --- a/core/res/res/values-hy-rAM/strings.xml +++ b/core/res/res/values-hy-rAM/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Թույլ է տալիս սեփականատիրոջը միանալ Vpn ծառայության վերին մակարդակի ինտերֆեյսին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"միանալ պաստառին"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Թույլ է տալիս սեփականատիրոջը միանալ պաստառի վերին մակարդակի ինտերֆեյսին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"միանալ հեռակա էկրանին"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Թույլ է տալիս սեփականատիրոջը միանալ հեռակա էկրանի վերին մակարդակի ինտերֆեյսին: Սովորական ծրագրերի համար երբևէ չպետք է անհրաժեշտ լինի:"</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"միանալ վիջեթ ծառայությանը"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Թույլ է տալիս սեփականատիրոջը միանալ վիջեթ ծառայության վերին մակարդակի ինտերֆեյսին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"փոխգործակցել սարքի կառավարչի հետ"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Համակարգ"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-ի ձայնանյութ"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Անլար էկրան"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Կատարված է"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Մեդիա արտածում"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Միանալ սարքին"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Հեռարձակել էկրանը սարքի վրա"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Որոնվում են սարքեր..."</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Կարգավորումներ"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Անջատել"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Սկանավորում..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Միանում է..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Հասանելի է"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Վերածածկ #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>. <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> կմվ"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", անվտանգ"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Անլար ցուցադրումը կապակցված է"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Այս էկրանը ցուցադրվում է այլ սարքում"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Էկրանի հեռարձակում"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Միանում է <xliff:g id="NAME">%1$s</xliff:g>-ին"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Էկրանը հեռարձակվում է"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Միացված է <xliff:g id="NAME">%1$s</xliff:g>-ին"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Անջատել"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Արտակարգ իրավիճակի հեռախոսազանգ"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Մոռացել եմ սխեման"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index d6d91fb..633621a 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu layanan Vpn. Tidak pernah diperlukan oleh apl normal."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"mengikat ke wallpaper"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu wallpaper. Tidak pernah diperlukan oleh apl normal."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"mengikat ke layar jarak jauh"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Mengizinkan pemegang mengikat ke antarmuka tingkat atas dari layar jarak jauh. Tidak pernah diperlukan untuk aplikasi normal."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"mengikat ke layanan widget"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu layanan widget. Tidak pernah diperlukan oleh apl normal."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"berinteraksi dengan admin perangkat"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Layar nirkabel"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Selesai"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Keluaran media"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Sambungkan ke perangkat"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Transmisi layar ke perangkat"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Menelusuri perangkat…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Setelan"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Putuskan sambungan"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Memindai..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Menyambung..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Tersedia"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Hamparan #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", aman"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Layar nirkabel tersambung"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Layar ini ditampilkan di perangkat lain"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Transmisi layar"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Menyambung ke <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Transmisi layar"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Tersambung ke <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Putuskan sambungan"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Panggilan darurat"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Lupa Pola?"</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 88d69de..6bae95b 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Consente l\'associazione all\'interfaccia principale di un servizio VPN. Non dovrebbe mai essere necessario per le normali applicazioni."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"associazione a sfondo"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Consente l\'associazione di uno sfondo all\'interfaccia principale. Non dovrebbe mai essere necessaria per le normali applicazioni."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"collega a un display remoto"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Consente al titolare di collegarsi all\'interfaccia di primo livello di un display remoto. Non dovrebbe essere mai necessaria per le normali applicazioni."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"associazione a un servizio widget"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Consente l\'associazione all\'interfaccia principale di un servizio widget. Non dovrebbe mai essere necessario per le normali applicazioni."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interazione con un amministratore dispositivo"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Visualizzazione wireless"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fine"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Uscita media"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Connetti al dispositivo"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Trasmetti schermo al dispositivo"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Ricerca di dispositivi in corso…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Impostazioni"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Disconnetti"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Ricerca in corso..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Connessione..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Disponibile"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay n. <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", opzione sicura"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Il display wireless è connesso"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Questa schermata è mostrata su un altro dispositivo"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Trasmissione schermo"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Collegamento a <xliff:g id="NAME">%1$s</xliff:g> in corso"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Trasmissione schermo attiva"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Collegato a <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Disconnetti"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Chiamata di emergenza"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Sequenza dimenticata"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 8dcdac5..1d42f65 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"מאפשר למשתמש לבצע איגוד לממשק ברמה עליונה של שירות VPN. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"קשור לטפט"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"מאפשר למשתמש לבצע איגוד לממשק הרמה העליונה של טפט. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"איגוד לצג מרוחק"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"הרשאה זו מאפשרת למשתמש לבצע איגוד לממשק הרמה העליונה של צג רחוק. לעולם אינה אמורה להיות נחוצה לאפליקציות רגילות."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"הכפפה לשירות Widget"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"מאפשר למשתמש לבצע איגוד לממשק הרמה העליונה של שירות Widget. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"קיים אינטראקציה עם מנהל המכשיר"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"מערכת"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"אודיו Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"צג אלחוטי"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"סיום"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"פלט מדיה"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"התחברות למכשיר"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"העברת מסך אל מכשיר"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"מחפש מכשירים…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"הגדרות"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"התנתק"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"סורק..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"מתחבר..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"זמין"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"שכבת על #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", מאובטח"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"מסך אלחוטי מחובר"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"מסך זה מוצג במכשיר אחר"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"העברת מסך מתבצעת"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"מתחבר אל <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"העברת מסך מתבצעת"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"מחובר אל <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"נתק"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"שיחת חירום"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"שכחת את הקו"</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 0dc0a30..559d53f 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"VPNサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"壁紙にバインド"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"壁紙のトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"リモートディスプレイへのバインド"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"リモートディスプレイのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ウィジェットサービスにバインド"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ウィジェットサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"デバイス管理者との通信"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"システム"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth音声"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"ワイヤレスディスプレイ"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"完了"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"メディア出力"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"端末に接続"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"端末への画面のキャスト"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"端末を検索しています…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"設定"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"接続を解除"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"スキャン中..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"接続中..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"利用できます"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"オーバーレイ第<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>、<xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">"、セキュア"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"ワイヤレスディスプレイが接続されています"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"この画面は別の端末で表示されています"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"画面のキャスト中"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"<xliff:g id="NAME">%1$s</xliff:g>に接続しています"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"画面のキャスト中"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"<xliff:g id="NAME">%1$s</xliff:g>に接続しました"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"切断"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"緊急通報"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"パターンを忘れた場合"</string> diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml index efc85ba..7f4dc90 100644 --- a/core/res/res/values-ka-rGE/strings.xml +++ b/core/res/res/values-ka-rGE/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"აპს შეეძლება Vpn სერვისის ზედა დონის ინტერფეისთან დაკავშირება. არასდროს გამოიყენება ჩვეულებრივ აპებში."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"ფონზე მიჭედება"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"მფლობელს შეეძლება ფონის ზედა დონის ინტერფეისთან დაკავშირება. არასდროს გამოიყენება ჩვეულებრივ აპებში."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"დისტანციურ მონიტორზე მიბმა"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"მფლობელს შეეძლება მიებას დისტანციურ მონიტორის ზედა დონის ინტერფეისს. ჩვეულებრივ აპს ეს წესით არასოდეს უნდა დაჭირდეს."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ვიჯეტ სერვისთან დაკავშირება"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"აპს შეეძლება ზედა დონის ინტერფეისის ვიჯეტთან დაკავშირება. არასდროს გამოიყენება ჩვეულებრივ აპებში."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"მოწყობილობის ადმინთან ინტერაქცია"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"სისტემა"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth აუდიო"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"უსადენო ეკრანი"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"დასრულდა"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"მედია გამომავალი"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"მოწყობილობასთან დაკავშირება"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ეკრანის მოწყობილობაზე გადაცემა"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"მოწყობილობების ძიება…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"პარამეტრები"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"კავშირის გაწყვეტა"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"სკანირება..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"დაკავშირება..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"ხელმისაწვდომი"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"გადაფარვა #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", დაცული"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"უსადენო ეკრანი დაკავშირებულია"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"გამოსახულება გადაეცემა სხვა მოწყობილობას"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"მიმდინარეობს ეკრანის გადაცემა"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"<xliff:g id="NAME">%1$s</xliff:g>-თან დაკავშირება"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"მიმდინარეობს ეკრანის გადაცემა"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"დაკავშირებულია <xliff:g id="NAME">%1$s</xliff:g>-თან"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"კავშირის გაწყვეტა"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"გადაუდებელი დახმარების ზარი"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"დაგავიწყდათ ნიმუში"</string> diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml index 1014da4..3bf648b 100644 --- a/core/res/res/values-km-rKH/strings.xml +++ b/core/res/res/values-km-rKH/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"ឲ្យម្ចាស់ចងចំណុចប្រទាក់កម្រិតកំពូលនៃសេវាកម្ម Vpn ។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"ចងទៅផ្ទាំងរូបភាព"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"ឲ្យម្ចាស់ចងចំណុចប្រទាក់កម្រិតកំពូលនៃផ្ទាំងរូបភាព។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ភ្ជាប់ទៅការបង្ហាញពីចម្ងាយ"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"អនុញ្ញាតឲ្យម្ចាស់ភ្ជាប់ទៅចំណុចប្រទាក់កម្រិតកំពូលនៃការបង្ហាញពីចម្ងាយ។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ចងសេវាកម្មធាតុក្រាហ្វិក"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ឲ្យម្ចាស់ចងចំណុចប្រទាក់កម្រិតកំពូលនៃសេវាកម្មធាតុក្រាហ្វិក។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ទាក់ទងជាមួយអ្នកគ្រប់គ្រងឧបករណ៍"</string> @@ -788,7 +790,7 @@ <string name="imProtocolYahoo" msgid="8271439408469021273">"Yahoo"</string> <string name="imProtocolSkype" msgid="9019296744622832951">"Skype"</string> <string name="imProtocolQq" msgid="8887484379494111884">"QQ"</string> - <string name="imProtocolGoogleTalk" msgid="493902321140277304">"ការជជែក"</string> + <string name="imProtocolGoogleTalk" msgid="493902321140277304">"Hangouts"</string> <string name="imProtocolIcq" msgid="1574870433606517315">"ICQ"</string> <string name="imProtocolJabber" msgid="2279917630875771722">"Jabber"</string> <string name="imProtocolNetMeeting" msgid="8287625655986827971">"NetMeeting"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"ប្រព័ន្ធ"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"សំឡេងប៊្លូធូស"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"បង្ហាញបណ្ដាញឥតខ្សែ"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"រួចរាល់"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"លទ្ធផលមេឌៀ"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"ភ្ជាប់ឧបករណ៍"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ចាត់ថ្នាក់អេក្រង់ទៅឧបករណ៍"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"កំពុងស្វែងរកឧបករណ៍..."</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"ការកំណត់"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"ផ្ដាច់"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"កំពុងវិភាគរក…"</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"កំពុងភ្ជាប់…"</string> <string name="media_route_status_available" msgid="6983258067194649391">"ទំនេរ"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"#<xliff:g id="ID">%1$d</xliff:g> ត្រួតគ្នា"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", សុវត្ថិភាព"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"បានភ្ជាប់ការបង្ហាញបណ្ដាញឥតខ្សែ"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"អេក្រង់នេះបង្ហាញលើឧបករណ៍ផ្សេង"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"ចាត់ថ្នាក់អេក្រង់"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"កំពុងតភ្ជាប់ទៅ <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"ចាត់ថ្នាក់អេក្រង់"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"តភ្ជាប់ទៅ <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"ផ្ដាច់"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"ការហៅពេលអាសន្ន"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"ភ្លេចលំនាំ"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 2240069..d5eb619 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"권한을 가진 프로그램이 VPN 서비스에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"배경화면 연결"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"권한을 가진 프로그램이 배경화면에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"원격 디스플레이에 연결"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"권한을 가진 프로그램이 원격 디스플레이에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"위젯 서비스와 연결"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"권한을 가진 프로그램이 위젯 서비스에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"기기 관리자와 상호 작용"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"시스템"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"블루투스 오디오"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"무선 디스플레이"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"완료"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"미디어 출력"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"기기에 연결"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"기기로 화면 전송"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"기기 검색 중…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"설정"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"연결 해제"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"검색 중..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"연결 중..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"사용 가능"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"<xliff:g id="ID">%1$d</xliff:g>번째 오버레이"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", 보안"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"무선 디스플레이가 연결되었습니다."</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"이 화면은 다른 기기에서 표시되고 있습니다."</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"화면 전송 중"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"<xliff:g id="NAME">%1$s</xliff:g>에 연결 중"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"화면 전송 중"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"<xliff:g id="NAME">%1$s</xliff:g>에 연결됨"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"연결 해제"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"긴급 통화"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"패턴을 잊음"</string> diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml index b6de941..8d88dfee9f 100644 --- a/core/res/res/values-lo-rLA/strings.xml +++ b/core/res/res/values-lo-rLA/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງເຊື່ອມໂຍງກັບສ່ວນຕິດຕໍ່ລະດັບເທິງສຸດ ຂອງບໍລິການ VPN. ແອັບຯທົ່ວໄປບໍ່ຄວນຈຳເປັນຕ້ອງໃຊ້."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"ເຊື່ອມໂຍງກັບພາບພື້ນຫຼັງ"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"ອະນຸຍາດໃຫ້ຜູ່ໃຊ້ເຊື່ອມໂຍງກັບສ່ວນຕິດຕໍ່ລະດັບສູງສຸດ ຂອງພາບພື້ນຫຼັງໃດນຶ່ງ. ແອັບຯທຳມະດາບໍ່ຄວນຈຳເປັນຕ້ອງໃຊ້."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ຜູກກັນເພື່ອສະແດງຜົນທາງໄກ."</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"ອະນຸຍາດໃຫ້ຜູ່ຖືຜູກກັບສ່ວນຕິດຕໍ່ລະດັບສູງສຸດ ຂອງການສະແດງຜົນທາງໄກ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ເຊື່ອມໂຍງໄປຫາບໍລິການວິດເຈັດ"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ອະນຸຍາດໃຫ້ຜູ່ຖືຜູກກັບອິນເຕີເຟດລະດັບສູງສຸດ ຂອງບໍລິການວິເຈັດ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ຕິດຕໍ່ກັບຜູ່ເບິ່ງແຍງອຸປະກອນ"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"ລະບົບ"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"ສຽງ Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"ການສະແດງຜົນໄຮ້ສາຍ"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"ແລ້ວໆ"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"ມີເດຍເອົ້າພຸດ"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"ເຊື່ອມຕໍ່ຫາອຸປະກອນ"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ສົ່ງພາບໜ້າຈໍໄປຫາອຸປະກອນ"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"ກຳລັງຊອກຫາອຸປະກອນ..."</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"ການຕັ້ງຄ່າ"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"ຕັດການເຊື່ອມຕໍ່"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"ກຳລັງສະແກນ..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"ກຳລັງເຊື່ອມຕໍ່..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"ສາມາດໃຊ້ໄດ້"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"ການວາງຊ້ອນ #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", ປອດໄພ"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"ເຊື່ອມຕໍ່ການສະແດງຜົນໄຮ້ສາຍແລ້ວ"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"ຈໍນີ້ກຳລັງສະແດງຢູ່ໃນອຸປະກອນອື່ນ"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"ກຳລັງສົ່ງພາບໜ້າຈໍ"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"ກຳລັງເຊື່ອມຕໍ່ຫາ <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"ການສົ່ງພາບໜ້າຈໍ"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"ເຊື່ອມຕໍ່ກັບ <xliff:g id="NAME">%1$s</xliff:g> ແລ້ວ"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"ຢຸດການເຊື່ອມຕໍ່"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"ການໂທສຸກເສີນ"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"ລືມຮູບແບບປົດລັອກ?"</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index c32bd9d..614bcd6 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Leidžiama savininkui susisaistyti su aukščiausio lygio VPN paslaugos sąsaja. Įprastoms programoms to neturėtų prireikti."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"susaistyti su darbalaukio fonu"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Leidžiama savininką susaistyti su aukščiausio lygio darbalaukio fono sąsaja. Įprastoms programoms to neturėtų prireikti."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"susisaistyti su nuotoliniu ekranu"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Leidžiama savininkui susisaistyti su aukščiausiojo lygio nuotolinio ekrano sąsaja. Įprastoms programoms to neturėtų prireikti."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"susaistyti su valdiklio paslauga"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Leidžiama savininkui susisaistyti su aukščiausio lygio valdiklio paslaugos sąsaja. Įprastoms programoms to neturėtų prireikti."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"sąveikauti su įrenginio administratoriumi"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"„Bluetooth“ garsas"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Belaidis rodymas"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Atlikta"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Medijos išvestis"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Prijungimas prie įrenginio"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Perduoti ekraną į įrenginį"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Ieškoma įrenginių…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Nustatymai"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Atjungti"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Nuskaitoma..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Jungiama..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Pasiekiama"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Perdanga nr. <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"„<xliff:g id="NAME">%1$s</xliff:g>“: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> tašk. colyje"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", saugu"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Prijungtas belaidis monitorius"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Šis ekranas rodomas kitame įrenginyje"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Perduodamas ekranas"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Prisijungiama prie „<xliff:g id="NAME">%1$s</xliff:g>“"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Perduodamas ekranas"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Prisijungta prie „<xliff:g id="NAME">%1$s</xliff:g>“"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Atjungti"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Skambutis pagalbos numeriu"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Pamiršau atrakinimo piešinį"</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 66a5d73..9f3cb53 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Ļauj īpašniekam izveidot saiti ar VPN pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"saistīt ar tapeti"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Ļauj īpašniekam piesaistīt tapetes augstākā līmeņa lietotāja saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"Saites izveide ar attālu displeju"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Ļauj īpašniekam izveidot saiti ar attāla displeja augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"saistīt ar logrīka pakalpojumu"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ļauj īpašniekam izveidot saiti ar logrīka pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"mijiedarboties ar ierīces administratoru"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistēma"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Bezvadu attēlošana"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gatavs"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Multivides izeja"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Savienojuma izveide ar ierīci"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Ekrāna apraide uz ierīci"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Notiek ierīču meklēšana…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Iestatījumi"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Atvienot"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Notiek meklēšana..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Notiek savienojuma izveide..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Pieejams"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Pārklājums Nr. <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", drošs"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Bezvadu attēlošanas savienojums ir izveidots."</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Šis ekrāns tiek rādīts citā ierīcē."</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Ekrāna apraidīšana"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Notiek savienojuma izveide ar: <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Ekrāna apraidīšana"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Izveidots savienojums ar: <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Pārtraukt savienojumu"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Ārkārtas izsaukums"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Aizmirsu kombināciju"</string> diff --git a/core/res/res/values-mcc310-mnc260/config.xml b/core/res/res/values-mcc310-mnc260/config.xml index 886ecbe..d602c9f 100644 --- a/core/res/res/values-mcc310-mnc260/config.xml +++ b/core/res/res/values-mcc310-mnc260/config.xml @@ -21,22 +21,6 @@ for different hardware and product builds. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- Array of ConnectivityManager.TYPE_xxxx values allowable for tethering --> - <!-- Common options are [1, 4] for TYPE_WIFI and TYPE_MOBILE_DUN or - <!== [0,1,5,7] for TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI and TYPE_BLUETOOTH --> - <integer-array translatable="false" name="config_tether_upstream_types"> - <item>1</item> - <item>4</item> - <item>7</item> - <item>9</item> - </integer-array> - - <!-- String containing the apn value for tethering. May be overriden by secure settings - TETHER_DUN_APN. Value is a comma separated series of strings: - "name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type" - note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" --> - <string translatable="false" name="config_tether_apndata">T-Mobile Tethering,pcweb.tmobile.com,,,,,,,,,310,260,,DUN</string> - <!-- Configure mobile network MTU. Carrier specific value is set here. --> <integer name="config_mobile_mtu">1440</integer> diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml index 6ce299d..252a959 100644 --- a/core/res/res/values-mn-rMN/strings.xml +++ b/core/res/res/values-mn-rMN/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Эзэмшигч нь VPN үйлчилгээний дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"ханын зурагтай холбох"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Эзэмшигч нь ханын зурагны дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-уудад шаардлагагүй."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"алсын дэлгэцтэй холбогдох"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Эзэмшигчид алсын дэлгэц дэх дээд давхаргын интерфэйстэй холбогдох боломж олгоно. Энгийн апп-д шаардагдахгүй."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"виджет үйлчилгээтэй холбох"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Эзэмшигч нь виджет үйлчилгээний дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"төхөөрөмжийн админтай харилцан үйлчлэх"</string> @@ -788,7 +790,7 @@ <string name="imProtocolYahoo" msgid="8271439408469021273">"Yahoo"</string> <string name="imProtocolSkype" msgid="9019296744622832951">"Skype"</string> <string name="imProtocolQq" msgid="8887484379494111884">"QQ"</string> - <string name="imProtocolGoogleTalk" msgid="493902321140277304">"Цугларалт"</string> + <string name="imProtocolGoogleTalk" msgid="493902321140277304">"Hangouts"</string> <string name="imProtocolIcq" msgid="1574870433606517315">"ICQ"</string> <string name="imProtocolJabber" msgid="2279917630875771722">"Jabber"</string> <string name="imProtocolNetMeeting" msgid="8287625655986827971">"NetMeeting"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Систем"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Блютүүт аудио"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Утасгүй дэлгэц"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Дууссан"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Медиа гаралт"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Төхөөрөмжтэй холбох"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Дэлгэцийг төхөөрөмж рүү дамжуулах"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Төхөөрөмжүүдийг хайж байна…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Тохиргоо"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Салгах"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Скан хийж байна..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Холбогдож байна..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Боломжтой"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Давхарга #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", найдвартай"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Утасгүй дэлгэц холбогдов"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Энэ дэлгэц өөр төхөөрөмжийг харуулж байна"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Дэлгэцийг дамжуулж байна"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"<xliff:g id="NAME">%1$s</xliff:g> руу холбогдож байна"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Дэлгэцийг дамжуулж байна"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"<xliff:g id="NAME">%1$s</xliff:g> руу холбогдсон"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Салгах"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Яаралтай дуудлага"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Хээг мартсан"</string> diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml index 8203921..284837a 100644 --- a/core/res/res/values-ms-rMY/strings.xml +++ b/core/res/res/values-ms-rMY/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan Vpn. Tidak sekali-kali diperlukan untuk apl biasa."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"terikat pada kertas dinding"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi kertas dinding. Tidak sekali-kali diperlukan untuk apl biasa."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"terikat kepada paparan jauh"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi paparan jauh. Tidak sekali-kali diperlukan untuk apl biasa."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"terikat kepada perkhidmatan widget"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan widget. Tidak sekali-kali diperlukan untuk apl biasa."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"berinteraksi dengan pentadbir peranti"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Paparan wayarles"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Selesai"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Output media"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Sambung ke peranti"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Hantar skrin ke peranti"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Mencari peranti..."</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Tetapan"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Putuskan sambungan"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Mengimbas…"</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Menyambung..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Tersedia"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Tindih #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", selamat"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Paparan wayarles disambungkan"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Skrin ini ditunjukkan pada peranti lain"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Menghantar skrin"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Menyambung ke <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Menghantar skrin"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Disambungkan ke <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Putus sambungan"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Panggilan kecemasan"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Lupa Corak"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 8aed6f1..7b77a1c 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Lar innehaveren binde seg til det øverste nivået av grensesnittet for en VPN-tjeneste. Skal aldri være nødvendig for vanlige apper."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"binde til bakgrunnsbilde"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Lar innehaveren binde det øverste nivået av grensesnittet til en bakgrunn. Skal aldri være nødvendig for vanlige apper."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"binde til ekstern skjerm"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Lar innehaveren binde seg til det øverste grensesnittnivået for ekstern skjerm. Skal aldri være nødvendig for vanlige apper."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"binde til modultjenste"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lar innehaveren binde seg til det øverste nivået av grensesnittet for en modultjeneste. Skal aldri være nødvendig for vanlige apper."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunisere med enhetsadministrator"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-lyd"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Trådløs skjerm"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Fullført"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Medieutgang"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Koble til enheten"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Send skjermen til enheten"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Søker etter enheter …"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Innstillinger"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Koble fra"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Skanner ..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Kobler til ..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Tilgjengelig"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlegg #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", sikker"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Trådløs skjermdeling er tilkoblet"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Denne skjermen vises på en annen enhet"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Sender skjermen …"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Kobler til <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Sender skjermen …"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Koblet til <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Koble fra"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Nødnummer"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Har du glemt mønsteret?"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 5838aef..ba221cc 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Staat de houder toe verbinding te maken met de hoofdinterface van een VPN-service. Nooit vereist voor normale apps."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"verbinden met een achtergrond"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Hiermee wordt de houder toegestaan zich te verbinden met de hoofdinterface van een achtergrond. Nooit vereist voor normale apps."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"verbinding maken met een extern display"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Hiermee wordt de houder toegestaan verbinding te maken met de hoofdinterface van een extern display. Nooit vereist voor normale apps."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"verbinden met een widgetservice"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Hiermee wordt de houder toegestaan verbinding te maken met de hoofdinterface van een widgetservice. Nooit vereist voor normale apps."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactie met apparaatbeheer"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Systeem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Draadloze weergave"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gereed"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Media-uitvoer"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Verbinding maken met apparaat"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Scherm sturen naar apparaat"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Zoeken naar apparaten…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Instellingen"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Verbinding verbreken"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Scannen..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Verbinden..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Beschikbaar"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", beveiligd"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Draadloze weergave is aangesloten"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Dit scherm wordt op een ander apparaat weergegeven"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Scherm sturen"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Verbinden met <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Scherm sturen"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Verbonden met <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Verbinding verbreken"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Noodoproep"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Patroon vergeten"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 847f9cc..217d2c9 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Pozwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi VPN. Nie powinno być nigdy potrzebne w przypadku zwykłych aplikacji."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"powiązanie z tapetą"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Pozwala na tworzenie powiązania z interfejsem najwyższego poziomu tapety. Nieprzeznaczone dla zwykłych aplikacji."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"powiązanie z wyświetlaczem zdalnym"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu wyświetlacza zdalnego. Nieprzeznaczone dla zwykłych aplikacji."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"powiązanie z usługą widżetów"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi widżetów. Nie powinno być nigdy potrzebne w przypadku zwykłych aplikacji."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interakcja z administratorem urządzenia"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Dźwięk Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Wyświetlacz bezprzewodowy"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Gotowe"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Wyjście multimediów"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Połącz z urządzeniem"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Prezentuj ekran na urządzeniu"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Szukam urządzeń…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Ustawienia"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Rozłącz"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Skanuję..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Łączę..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Dostępne"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Nakładka nr <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", bezpieczny"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Podłączony jest wyświetlacz bezprzewodowy"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Ten ekran jest wyświetlany na innym urządzeniu"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Rozpoczynam prezentowanie ekranu"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Łączę z <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Trwa prezentowanie ekranu"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Połączono z <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Rozłącz"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Połączenie alarmowe"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Nie pamiętam wzoru"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 2aa5e9a..2d69f9c 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite que o titular se vincule à interface de nível superior de um serviço de VPN. Nunca deverá ser necessário para aplicações normais."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"vincular a uma imagem de fundo"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite ao titular vincular-se à interface de nível superior de uma imagem de fundo. Nunca deverá ser necessário para aplicações normais."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"associar a um ecrã remoto"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite ao detentor associar a interface de nível superior a um ecrã remoto. Nunca deve ser necessário para aplicações normais."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincular a um serviço de widget"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite que o titular vincule a interface de nível superior de um serviço de widget. Nunca deverá ser necessário para aplicações normais."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir com um administrador do dispositivo"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Áudio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Visualização sem fios"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Concluído"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Saída de som multimédia"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Ligar ao dispositivo"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Transmitir ecrã para o dispositivo"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"A pesquisar dispositivos…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Definições"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Desligar"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"A procurar..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"A ligar..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Disponível"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Sobreposição #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> ppp"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", protegido"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"O Display sem fios está ligado"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Este ecrã está a ser apresentado noutro dispositivo"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"A transmitir o ecrã"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"A ligar a <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"A transmitir o ecrã"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Ligado a <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Desligar"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Chamada de emergência"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Esqueceu-se da Sequência"</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index b13044f..f1ad4d7 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite que seu proprietário sujeite a interface de alto nível de um serviço de VPN. Nunca deve ser necessário para aplicativos normais."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"sujeitar-se a um plano de fundo"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite que o proprietário utilize interface de nível superior de um plano de fundo. Nunca deve ser necessário para aplicativos normais."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"usar uma tela remota"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite que o proprietário use a interface de nível superior de uma tela remota. Não deve ser necessário para aplicativos comuns."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"sujeitar-se a um serviço de widget"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite que o proprietário utilize a interface de nível superior de um serviço de widget. Nunca deve ser necessário para aplicativos normais."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir com o administrador de um dispositivo"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Áudio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Display sem fio"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Concluído"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Saída de mídia"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Conectar ao dispositivo"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Transmitir tela para dispositivo"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Procurando dispositivos…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Configurações"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Desconectar"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Verificando..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Conectando..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Disponível"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Sobreposição nº <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", seguro"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"O Display sem fio está conectado"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Tela exibida em outro dispositivo."</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Transmitindo a tela"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Conectando a <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Transmitindo a tela"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Conectado a <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Desconectar"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Chamada de emergência"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Esqueci o padrão"</string> diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml index 5c56441..6ea1e9e 100644 --- a/core/res/res/values-rm/strings.xml +++ b/core/res/res/values-rm/strings.xml @@ -598,6 +598,10 @@ <string name="permlab_bindWallpaper" msgid="8716400279937856462">"sa fixar vid in fund davos"</string> <!-- no translation found for permdesc_bindWallpaper (7108428692595491668) --> <skip /> + <!-- no translation found for permlab_bindRemoteDisplay (1782923938029941960) --> + <skip /> + <!-- no translation found for permdesc_bindRemoteDisplay (1261242718727295981) --> + <skip /> <!-- no translation found for permlab_bindRemoteViews (5697987759897367099) --> <skip /> <!-- no translation found for permdesc_bindRemoteViews (4717987810137692572) --> @@ -2411,10 +2415,18 @@ <skip /> <!-- no translation found for wireless_display_route_description (9070346425023979651) --> <skip /> - <!-- no translation found for media_route_chooser_grouping_done (7966438307723317169) --> - <skip /> <!-- no translation found for media_route_button_content_description (5758553567065145276) --> <skip /> + <!-- no translation found for media_route_chooser_title (1751618554539087622) --> + <skip /> + <!-- no translation found for media_route_chooser_title_for_remote_display (3395541745872017583) --> + <skip /> + <!-- no translation found for media_route_chooser_searching (4776236202610828706) --> + <skip /> + <!-- no translation found for media_route_chooser_extended_settings (87015534236701604) --> + <skip /> + <!-- no translation found for media_route_controller_disconnect (8966120286374158649) --> + <skip /> <!-- no translation found for media_route_status_scanning (7279908761758293783) --> <skip /> <!-- no translation found for media_route_status_connecting (6422571716007825440) --> @@ -2435,9 +2447,13 @@ <skip /> <!-- no translation found for display_manager_overlay_display_secure_suffix (6022119702628572080) --> <skip /> - <!-- no translation found for wifi_display_notification_title (2223050649240326557) --> + <!-- no translation found for wifi_display_notification_connecting_title (2838646471050359706) --> + <skip /> + <!-- no translation found for wifi_display_notification_connecting_message (5837350993752841389) --> + <skip /> + <!-- no translation found for wifi_display_notification_connected_title (8567308065912676285) --> <skip /> - <!-- no translation found for wifi_display_notification_message (4498802012464170685) --> + <!-- no translation found for wifi_display_notification_connected_message (2587209325701109715) --> <skip /> <!-- no translation found for wifi_display_notification_disconnect (6183754463561153372) --> <skip /> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index f29a7e6..c3f9157 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unui serviciu VPN. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"conectare la o imagine de fundal"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unei imagini de fundal. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"conectare la un ecran la distanță"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite proprietarului să se conecteze la interfața de nivel superior a unui ecran la distanță. Nu ar trebui să fie niciodată necesară pentru aplicațiile obișnuite."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"conectare la un serviciu widget"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unui serviciu widget. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interacţionare cu administratorul unui dispozitiv"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Ecran wireless"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Terminat"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Rezultate media"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Conectați-vă la dispozitiv"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Trimiteți ecranul pe dispozitiv"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Se caută dispozitive..."</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Setări"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Deconectați-vă"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Se scanează..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Se conectează..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Disponibilă"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Suprapunerea <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", securizat"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Ecranul wireless este conectat"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Acest ecran este afişat pe alt gadget"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Se trimite ecranul"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Se conectează la <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Se trimite ecranul"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Conectat la <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Deconectaţi-vă"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Apel de urgenţă"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Model uitat"</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 44db6b6..13f18c3 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Приложение сможет подключаться к базовому интерфейсу службы VPN. Это разрешение не используется обычными приложениями."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"Привязка к фоновому рисунку"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Приложение сможет подключаться к базовому интерфейсу службы обоев. Это разрешение не используется обычными приложениями."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"Подключение к удаленному дисплею"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Приложение сможет подключаться к базовому интерфейсу удаленного дисплея. Это разрешение обычно используется только специальными приложениями."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"Подключение к службе виджетов"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Приложение сможет подключаться к базовому интерфейсу службы виджетов. Это разрешение не используется обычными приложениями."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"Взаимодействие с администратором устройства"</string> @@ -1348,7 +1350,7 @@ <string name="submit" msgid="1602335572089911941">"Отправить"</string> <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Включен режим \"Штурман\""</string> <string name="car_mode_disable_notification_message" msgid="8035230537563503262">"Чтобы выйти, нажмите здесь."</string> - <string name="tethered_notification_title" msgid="3146694234398202601">"USB-модем/точка доступа Wi-Fi используется"</string> + <string name="tethered_notification_title" msgid="3146694234398202601">"Включен режим модема"</string> <string name="tethered_notification_message" msgid="6857031760103062982">"Нажмите для настройки."</string> <string name="back_button_label" msgid="2300470004503343439">"Назад"</string> <string name="next_button_label" msgid="1080555104677992408">"Далее"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Система"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Воспроизведение звука через Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Беспроводной монитор"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Перенаправлять поток мультимедиа"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Подключение к устройству"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Подключение к удаленному дисплею"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Поиск устройств…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Настройки"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Отключить"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Сканирование..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Подключение..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Доступен"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Наложение № <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> х <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> тчк/дюйм"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", безопасный"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Беспроводной проектор подключен"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Изображение передается на другое устройство"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Подключение к удаленному дисплею"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Подключение к <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Удаленный дисплей подключен"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Подключено к <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Отключить"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Экстренный вызов"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Забыли графический ключ?"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index a4e57fb..3467b4d 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby VPN. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"väzba na tapetu"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania tapety. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"viazať na vzdialený displej"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania vzdialeného displeja. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"viazať sa k službe miniaplikácie"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby miniaplikácií. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"komunikovať so správcom zariadenia"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Systém"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Bezdrôtový displej"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Hotovo"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Výstup médií"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Pripojenie k zariadeniu"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Odovzdanie obraz. na prehratie v zariad."</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Prebieha vyhľadávanie zariadení…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Nastavenia"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Odpojiť"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Prebieha vyhľadávanie..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Prebieha pripájanie…"</string> <string name="media_route_status_available" msgid="6983258067194649391">"K dispozícii"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Prekrytie č. <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", zabezpečené"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Bezdrôtový displej je pripojený"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Táto obrazovka sa zobrazuje na inom zariadení"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Odovzdávanie obrazovky na prehratie"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Prebieha pripájanie k obrazovke <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Odovzdávanie obrazovky na prehratie"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Pripojené k obrazovke <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Odpojiť"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Tiesňové volanie"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Nepamätám si vzor"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index c364397..0d76bbf 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Lastniku omogoča povezovanje z vmesnikom storitve navideznega zasebnega omrežja najvišje ravni. Ne uporabljajte za navadne programe."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"povezovanje z ozadjem"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Imetniku omogoča povezavo z vmesnikom ozadja najvišje ravni. Tega nikoli ni treba uporabiti za navadne programe."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"povezava z oddaljenim prikazom"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Imetniku omogoča povezovanje z vmesnikom oddaljenega prikaza najvišje ravni. Tega ni treba nikoli uporabiti za navadne aplikacije."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"poveži s storitvijo pripomočka"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lastniku omogoča povezovanje z vmesnikom storitve pripomočka najvišje ravni. Tega ni treba nikoli uporabiti za navadne programe."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interakcija s skrbnikom naprave"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Zvok prek Bluetootha"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Brezžični prikaz"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Končano"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Izhod predstavnosti"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Povezovanje z napravo"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Predvajanje zaslona v napravi"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Iskanje naprav …"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Nastavitve"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Prekinitev povezave"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Pregledovanje ..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Vzpostavljanje povezave ..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Na voljo"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Prekrivanje #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> pik na palec"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", varen"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Brezžični zaslon je povezan"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Ta zaslon je prikazan v drugi napravi"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Predvajanje zaslona"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Povezovanje z zaslonom <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Predvajanje zaslona"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Vzpostavljena povezava z zaslonom <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Prekini povezavo"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Klic v sili"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Pozabljen vzorec"</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index 605cde5..6fb9ea2 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Дозвољава власнику да се повеже са интерфејсом VPN услуге највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"обавезивање на позадину"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Дозвољава власнику да се повеже са интерфејсом позадине највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"повезивање са удаљеним екраном"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Дозвољава власнику да се повеже са интерфејсом удаљеног екрана највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"обавезивање на услугу виџета"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Дозвољава власнику да се обавеже на интерфејс услуге виџета највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"интеракција са администратором уређаја"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Систем"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth аудио"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Бежични екран"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Излаз медија"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Повежите са уређајем"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Пребаците екран на уређај"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Тражење уређаја…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Подешавања"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Прекини везу"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Скенирање..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Повезивање..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Доступна"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Постављени елемент бр. <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>×<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", безбедно"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Бежични екран је повезан"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Овај екран се приказује на другом уређају"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Пребацивање екрана"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Повезивање са <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Пребацивање екрана"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Повезано је са <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Прекини везу"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Хитни позив"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Заборављени шаблон"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 86eaa11..db7d7d0 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en VPN-tjänst. Ska inte behövas för vanliga appar."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"binda till en bakgrund"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Innehavaren kan binda till den översta nivåns gränssnitt för en bakgrund. Ska inte behövas för vanliga appar."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bind till en fjärrskärm"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en fjärrskärm. Ska inte behövas för vanliga appar."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind till en widget"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en widget. Ska inte behövas för vanliga appar."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"arbeta med en enhetsadministratör"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-ljud"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Trådlös skärm"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Klar"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Medieuppspelning"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Anslut till enhet"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Överför skärmen till enheten"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Söker efter enheter ..."</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Inställningar"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Koppla från"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Skannar…"</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Ansluter ..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Tillgängliga"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Överlagring #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", säker"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Trådlös anslutning till skärm"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Den här skärmen visas på en annan enhet"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Överför skärmen"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Ansluter till <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Överför skärmen"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Ansluten till <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Koppla från"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Nödsamtal"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Har du glömt ditt grafiska lösenord?"</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index aa4b279..30c8092 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Inaruhusu kishikiliaji kushurutisha kusano ya kiwango cha juu cha huduma ya Vpn. Haipaswi kuhitajika kwa programu za kawaida."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"funga kwa mandhari"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Inaruhusu kishikiliaji kushurutisha kwa kusano ya kiwango cha juu cha mandhari. Haipaswi kamwe kuhitajika kwa programu za kawaida."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"fungisha kwenye mwonekano wa mbali"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Huruhusu mtumiaji kujifungia kiolesura cha kiwango cha juu cha mwonekano wa mbali. Haipaswi kuhitajika kwa programu za kawaida."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"funga kwenye huduma ya widget"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Inaruhusu mmiliki kushurutisha kusano ya kiwango cha juu ya huduma ya wijeti. Haipaswi kuhitajika kwa programu za kawaida."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"jiunge na msimamizi wa kifaa"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Mfumo"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Sauti ya Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Uonyeshaji usiotumia waya"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Nimemaliza"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Towe la midia"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Unganisha kwenye kifaa"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Tuma skrini kwa kifaa"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Inatafuta vifaa..."</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Mipangilio"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Ondoa"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Inatambaza..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Inaunganisha..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Inapatikana"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Uwekeleaji #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", salama"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Onyesho pasiwaya limeunganishwa"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Skrini hii inaonyesha kwenye kifaa kingine"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Utumaji wa skrini"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Inaunganishwa kwenye <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Utumaji wa skrini"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Imeungwanishwa kwenye <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Tenganisha"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Simu ya dharura"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Umesahau Ruwaza"</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 4622005..f298a8f 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"อนุญาตให้เจ้าของเชื่อมโยงกับส่วนติดต่อผู้ใช้ระดับสูงสุดของบริการ VPN ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"เชื่อมโยงกับวอลเปเปอร์"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"อนุญาตให้ผู้ใช้เชื่อมโยงกับส่วนติดต่อผู้ใช้ระดับสูงสุดของวอลเปเปอร์ ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ผูกกับจอแสดงผลระยะไกล"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"อนุญาตให้ผู้ใช้ผูกกับอินเทอร์เฟซระดับสูงสุดของจอแสดงผลระยะไกล ซึ่งแอปพลิเคชันทั่วไปไม่จำเป็นต้องใช้"</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"เชื่อมโยงกับบริการวิดเจ็ต"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"อนุญาตให้ผู้ใช้เชื่อมโยงกับส่วนติดต่อผู้ใช้ระดับสูงสุดของบริการวิดเจ็ต ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ติดต่อกับผู้ดูแลอุปกรณ์"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"ระบบ"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"เสียงบลูทูธ"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"การแสดงผลแบบไร้สาย"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"เสร็จสิ้น"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"เอาต์พุตสื่อ"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"เชื่อมต่อกับอุปกรณ์"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ส่งหน้าจอไปยังอุปกรณ์"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"กำลังค้นหาอุปกรณ์…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"การตั้งค่า"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"ยกเลิกการเชื่อมต่อ"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"กำลังสแกน..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"กำลังเชื่อมต่อ..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"พร้อมใช้งาน"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"การวางซ้อน #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", ปลอดภัย"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"เชื่อมต่อการแสดงผลแบบไร้สายอยู่"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"หน้าจอนี้กำลังแสดงบนอุปกรณ์อื่น"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"กำลังส่งหน้าจอ"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"กำลังเชื่อมต่อไปยัง <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"กำลังส่งหน้าจอ"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"เชื่อมต่อกับ <xliff:g id="NAME">%1$s</xliff:g> แล้ว"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"หยุดเชื่อมต่อ"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"หมายเลขฉุกเฉิน"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"ลืมรูปแบบใช่หรือไม่"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 897a111..85dd968 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Pinapayagan ang may-hawak na sumailalim sa nangungunang interface ng serbisyo ng Vpn. Hindi kailanman dapat na kailanganin para sa normal na apps."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"sumailalim sa wallpaper"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Pinapayagan ang may-hawak na sumailalim sa nangungunang interface ng isang wallpaper. Hindi kailanman dapat na kailanganin para sa normal na apps."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"magpasaklaw sa isang remote na display"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Binibigyang-daan ang may-hawak na masaklaw ang pinakamataas na antas ng interface ng isang remote na display. Hindi dapat kailanman kailanganin ng normal na apps."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"itali sa serbisyo ng widget"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Pinapayagan ang may-hawak na sumailalim sa nangungunang interface ng serbisyo ng widget. Hindi kailanman dapat na kailanganin para sa normal na apps."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"makipag-ugnay sa tagapangasiwa ng device"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio sa Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Wireless display"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Tapos na"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Output ng media"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Kumonekta sa device"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"I-cast ang screen sa device"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Naghahanap ng mga device…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Mga Setting"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Idiskonekta"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Nagsa-scan..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Kumukonekta..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Available"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", secure"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Nakakonekta ang wireless na display"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Lumalabas ang screen na ito sa isa pang device"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Kina-cast ang screen"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Kumokonekta sa <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Kina-cast ang screen"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Nakakonekta sa <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Alisin sa pagkakakonekta"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Emergency na tawag"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Nakalimutan ang Pattern"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index ffb6ca1..9ca752e 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Cihazın sahibine bir VPN hizmetinin en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bir duvar kağıdına tabi kıl"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Cihazın sahibine, duvar kağıdının en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"uzak ekrana bağlan"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"İzin sahibine, bir uzak ekranın en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bir widget hizmetine bağla"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Cihazın sahibine bir widget hizmetinin en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"bir cihaz yöneticisi ile etkileşimde bulun"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth ses"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Kablosuz ekran"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Tamamlandı"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Medya çıkışı"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Cihaza bağlanın"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Ekranı cihaza yayınlayın"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Cihaz aranıyor…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Ayarlar"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Bağlantıyı kes"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Taranıyor..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Bağlanılıyor..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Kullanılabilir"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Yer Paylaşımı No. <xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", güvenli"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Kablosuz ekrana bağlandı"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Bu ekran başka bir cihazda gösteriliyor"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Ekran yayınlanıyor"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"<xliff:g id="NAME">%1$s</xliff:g> bağlantısı yapılıyor"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Ekran yayınlanıyor"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"<xliff:g id="NAME">%1$s</xliff:g> bağlantısı yapıldı"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Bağlantıyı kes"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Acil durum çağrısı"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Deseni Unuttunuz mu?"</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index f6bc23d..556b35b 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня служби VPN. Ніколи не застосовується для звичайних програм."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"прив’язати до фонового малюнка"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Дозволяє власнику прив’язуватися до інтерфейсу верхнього рівня фонового малюнка. Ніколи не застосовується для звичайних програм."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"прив’язуватися до віддаленого екрана"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня віддаленого екрана. Ніколи не застосовується для звичайних програм."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"прив\'язувати до служби віджетів"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня служби віджетів. Ніколи не застосовується для звичайних програм."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"взаємодіяти з адмін. пристрою"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Система"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Аудіо Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Бездротовий екран"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Готово"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Вивід медіа-даних"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Під’єднатися до пристрою"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Транслювати екран на пристрій"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Пошук пристроїв…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Налаштування"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Від’єднатися"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Сканування..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"З’єднання..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Доступно"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Накладання №<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>х<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", безпечний"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Бездротовий екран під’єднано"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Цей екран відображається на іншому пристрої"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Транслювання екрана"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"<xliff:g id="NAME">%1$s</xliff:g> – під’єднання"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Транслювання екрана"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"<xliff:g id="NAME">%1$s</xliff:g> – під’єднано"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Від’єднати"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Екстрений виклик"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Не пам’ятаю ключ"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index ec68f3a..c8f5014 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ Vpn. Không cần thiết cho các ứng dụng thông thường."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"liên kết với hình nền"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của hình nền. Không cần thiết cho các ứng dụng thông thường."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"liên kết với màn hình từ xa"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của màn hình từ xa. Không cần thiết cho các ứng dụng thông thường."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"liên kết với dịch vụ tiện ích con"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ tiện ích con. Không cần thiết cho các ứng dụng thông thường."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"tương tác với quản trị viên thiết bị"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Hệ thống"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Âm thanh Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Hiển thị không dây"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Xong"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Đầu ra phương tiện"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Kết nối với thiết bị"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Truyền màn hình tới thiết bị"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Đang tìm kiếm thiết bị…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Cài đặt"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Ngắt kết nối"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Đang quét..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Đang kết nối..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Khả dụng"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Lớp phủ #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", an toàn"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Hiển thị không dây đã được kết nối"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Màn hình này đang hiển thị trên thiết bị khác"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Truyền màn hình"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Đang kết nối với <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Truyền màn hình"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Đã kết nối với <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Ngắt kết nối"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Cuộc gọi khẩn cấp"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Đã quên hình"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 180accb..ba226af 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"允许用户绑定到 VPN 服务的顶级接口。普通应用绝不需要此权限。"</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"绑定到壁纸"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"允许用户绑定到壁纸的顶级接口。普通应用绝不需要此权限。"</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"绑定至远程显示屏"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"允许应用绑定至远程显示屏的顶级接口。普通应用绝不需要此权限。"</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"绑定到小部件服务"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允许应用绑定到小部件服务的顶级接口。普通应用绝不需要此权限。"</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"与设备管理器交互"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"系统"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"蓝牙音频"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"无线显示"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"完成"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"媒体输出线路"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"连接到设备"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"将屏幕投射到设备上"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"正在搜索设备…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"设置"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"断开连接"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"正在扫描..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"正在连接..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"可连接"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"叠加视图 #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>:<xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>,<xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">",安全"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"已连接到无线显示设备"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"此屏幕的内容正显示在另一台设备上"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"正在投射屏幕"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"正在连接到“<xliff:g id="NAME">%1$s</xliff:g>”"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"正在投射屏幕"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"已连接到“<xliff:g id="NAME">%1$s</xliff:g>”"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"断开连接"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"紧急呼救"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"忘记了图案"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 0fd3fdb..fa0c49b 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"允許應用程式繫結至 VPN 服務的頂層介面 (不建議一般應用程式使用)。"</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"繫結至桌布"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"允許應用程式繫結至桌布的頂層介面 (不建議一般應用程式使用)。"</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"繫結至遠端螢幕"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"允許應用程式繫結至遠端屏螢的頂層介面 (不建議一般應用程式使用)。"</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"繫結至小工具服務"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允許應用程式繫結至小工具服務的頂層介面 (不建議一般應用程式使用)。"</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"與裝置管理員互動"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"系統"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"藍牙音頻"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"無線螢幕分享"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"完成"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"媒體輸出"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"連接裝置"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"在裝置上放送螢幕"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"正在搜尋裝置…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"設定"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"停止連接"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"正在掃描…"</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"正在連線..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"可用"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"重疊效果 #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>:<xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>,<xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">"(安全)"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"已連接無線顯示裝置"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"這個畫面正在另一部裝置上顯示"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"正在放送螢幕"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"正在連線到「<xliff:g id="NAME">%1$s</xliff:g>」"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"正在放送螢幕"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"已連線到「<xliff:g id="NAME">%1$s</xliff:g>」"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"中斷連線"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"緊急電話"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"忘記圖案"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 8f8ccdd..40d6260 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"允許應用程式聯繫至 VPN 服務的頂層介面 (一般應用程式不需使用)。"</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"連結至桌布"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"允許應用程式繫結至桌布的頂層介面 (一般應用程式不需使用)。"</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"繫結至遠端螢幕"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"允許應用程式繫結至遠端螢幕的頂層介面 (一般應用程式不需使用)。"</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"繫結至小工具服務"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允許應用程式繫結至小工具服務的頂層介面 (一般應用程式不需使用)。"</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"與裝置管理員互動"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"系統"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"藍牙音訊"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"無線螢幕分享"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"完成"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"媒體輸出"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"連線至裝置"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"將螢幕投放到裝置上"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"正在搜尋裝置..."</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"設定"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"中斷連線"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"掃描中..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"連線中…"</string> <string name="media_route_status_available" msgid="6983258067194649391">"可以使用"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"第 <xliff:g id="ID">%1$d</xliff:g> 個重疊效果"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>:<xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>,<xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">"(安全)"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"已連接無線顯示器"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"其他裝置正在顯示這個畫面"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"正在投放螢幕"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"正在連線至「<xliff:g id="NAME">%1$s</xliff:g>」"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"正在投放螢幕"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"已連線至「<xliff:g id="NAME">%1$s</xliff:g>」"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"中斷連線"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"緊急電話"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"忘記圖形"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 9f47a5c..563cb3f 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -382,6 +382,8 @@ <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Ivumela umnini ukuthi abophele kwissekelo esingaphezulu sesevisi ye-Vpm. Ayidingakeli izinhlelo zokusebenza ezejwayelekile."</string> <string name="permlab_bindWallpaper" msgid="8716400279937856462">"hlanganisa kwiphephadonga"</string> <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Ivumela umbambi ukuhlanganisa uxhumano nomsebenzisi kwezinga eliphezulu lwephephadonga. Akusoze kwadingeka kwezinhlelo zokusebenza ezivamile."</string> + <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bophezela kusibonisi sesilawuli kude"</string> + <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Ivumela umbambi ukuhlanganisa isixhumi esibonakalayo esisezingeni eliphezulu sesibonisi sesilawuli kude. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string> <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bophezela kube isevisi yesinqunjana"</string> <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ivumela umbambi ukuhlanganisa uxhumano nomsebenzisi kwezinga eliphezulu lensizakalo yesinqunjwana. Akusoze kwadingeka kwezinhlelo zokusebenza ezivamile."</string> <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"xhumana nomphathi wedivaysi"</string> @@ -1489,8 +1491,12 @@ <string name="default_audio_route_category_name" msgid="3722811174003886946">"Isistimu"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Umsindo we-Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Ukubonisa okungenazintambo"</string> - <string name="media_route_chooser_grouping_done" msgid="7966438307723317169">"Qedile"</string> <string name="media_route_button_content_description" msgid="5758553567065145276">"Okukhiphayo kwemidiya"</string> + <string name="media_route_chooser_title" msgid="1751618554539087622">"Xhuma kudivayisi"</string> + <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Lingisa isikrini kudivayisi"</string> + <string name="media_route_chooser_searching" msgid="4776236202610828706">"Isesha amadivayisi…"</string> + <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"Izilungiselelo"</string> + <string name="media_route_controller_disconnect" msgid="8966120286374158649">"Nqamula"</string> <string name="media_route_status_scanning" msgid="7279908761758293783">"Iyaskena..."</string> <string name="media_route_status_connecting" msgid="6422571716007825440">"Iyaxhuma..."</string> <string name="media_route_status_available" msgid="6983258067194649391">"Kuyatholakala"</string> @@ -1501,8 +1507,10 @@ <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Isendlalelo #<xliff:g id="ID">%1$d</xliff:g>"</string> <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string> <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", kuphephile"</string> - <string name="wifi_display_notification_title" msgid="2223050649240326557">"Ukubukeka okungenantambo kuxhunyiwe"</string> - <string name="wifi_display_notification_message" msgid="4498802012464170685">"Lesi sikrini siyabonakala kwenye idivayisi"</string> + <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Isikrini sokulingisa"</string> + <string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Ixhuma ku-<xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Isikrini sokulingisa"</string> + <string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Kuxhunywe ku-<xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Nqamula"</string> <string name="kg_emergency_call_label" msgid="684946192523830531">"Ucingo lwezimo eziphuthumayo"</string> <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Ukhohlwe iphethini?"</string> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 18cf57d..b34c792 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1189,6 +1189,9 @@ <item>12</item> <!-- EVDO_B --> </integer-array> + <!-- Set to true if after a provisioning apn the radio should be restarted --> + <bool name="config_restartRadioAfterProvisioning">false</bool> + <!-- Vibrator pattern to be used as the default for notifications that specify DEFAULT_VIBRATE. --> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 62f26c6..9025400 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1052,6 +1052,12 @@ interface of a wallpaper. Should never be needed for normal apps.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_bindRemoteDisplay">bind to a remote display</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_bindRemoteDisplay">Allows the holder to bind to the top-level + interface of a remote display. Should never be needed for normal apps.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_bindRemoteViews">bind to a widget service</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_bindRemoteViews">Allows the holder to bind to the top-level @@ -4090,12 +4096,24 @@ <!-- Description of a wireless display route. [CHAR LIMIT=50] --> <string name="wireless_display_route_description">Wireless display</string> - <!-- "Done" button for MediaRouter chooser dialog when grouping routes. [CHAR LIMIT=NONE] --> - <string name="media_route_chooser_grouping_done">Done</string> - <!-- Content description of a MediaRouteButton for accessibility support --> <string name="media_route_button_content_description">Media output</string> + <!-- Title of the media route chooser dialog. [CHAR LIMIT=40] --> + <string name="media_route_chooser_title">Connect to device</string> + + <!-- Title of the media route chooser dialog for selecting remote display routes. [CHAR LIMIT=40] --> + <string name="media_route_chooser_title_for_remote_display">Cast screen to device</string> + + <!-- Placeholder text to show when no devices have been found. [CHAR LIMIT=50] --> + <string name="media_route_chooser_searching">Searching for devices\u2026</string> + + <!-- Button to access extended settings. [CHAR LIMIT=30] --> + <string name="media_route_chooser_extended_settings">Settings</string> + + <!-- Button to disconnect from a media route. [CHAR LIMIT=30] --> + <string name="media_route_controller_disconnect">Disconnect</string> + <!-- Status message for remote routes attempting to scan/determine availability --> <string name="media_route_status_scanning">Scanning...</string> @@ -4128,10 +4146,14 @@ <!-- Title text to append when the display is secure. [CHAR LIMIT=30] --> <string name="display_manager_overlay_display_secure_suffix">, secure</string> + <!-- Title of the notification to indicate the process of connecting to a wifi display. [CHAR LIMIT=50] --> + <string name="wifi_display_notification_connecting_title">Casting screen</string> + <!-- Message of the notification to indicate the process of connecting to a wifi display. [CHAR LIMIT=80] --> + <string name="wifi_display_notification_connecting_message">Connecting to <xliff:g id="name">%1$s</xliff:g></string> <!-- Title of the notification to indicate an active wifi display connection. [CHAR LIMIT=50] --> - <string name="wifi_display_notification_title">Wireless display is connected</string> + <string name="wifi_display_notification_connected_title">Casting screen</string> <!-- Message of the notification to indicate an active wifi display connection. [CHAR LIMIT=80] --> - <string name="wifi_display_notification_message">This screen is showing on another device</string> + <string name="wifi_display_notification_connected_message">Connected to <xliff:g id="name">%1$s</xliff:g></string> <!-- Label of a button to disconnect an active wifi display connection. [CHAR LIMIT=25] --> <string name="wifi_display_notification_disconnect">Disconnect</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index b85bff4..6d90973 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -283,6 +283,7 @@ <java-symbol type="bool" name="config_safe_media_volume_enabled" /> <java-symbol type="bool" name="config_camera_sound_forced" /> <java-symbol type="bool" name="config_dontPreferApn" /> + <java-symbol type="bool" name="config_restartRadioAfterProvisioning" /> <java-symbol type="bool" name="config_speed_up_audio_on_mt_calls" /> <java-symbol type="bool" name="config_useFixedVolume" /> <java-symbol type="bool" name="config_forceDefaultOrientation" /> @@ -1096,7 +1097,11 @@ <java-symbol type="drawable" name="notification_template_icon_bg" /> <java-symbol type="drawable" name="notification_template_icon_low_bg" /> <java-symbol type="drawable" name="ic_media_route_on_holo_dark" /> + <java-symbol type="drawable" name="ic_media_route_off_holo_dark" /> + <java-symbol type="drawable" name="ic_media_route_connecting_holo_dark" /> <java-symbol type="drawable" name="ic_media_route_disabled_holo_dark" /> + <java-symbol type="drawable" name="ic_notification_cast_connecting" /> + <java-symbol type="drawable" name="ic_notification_cast_on" /> <java-symbol type="drawable" name="cling_button" /> <java-symbol type="drawable" name="cling_arrow_up" /> <java-symbol type="drawable" name="cling_bg" /> @@ -1253,17 +1258,17 @@ <java-symbol type="attr" name="mediaRouteButtonStyle" /> <java-symbol type="attr" name="externalRouteEnabledDrawable" /> - <java-symbol type="id" name="extended_settings" /> - <java-symbol type="id" name="check" /> - <java-symbol type="id" name="volume_slider" /> - <java-symbol type="id" name="volume_icon" /> - <java-symbol type="drawable" name="ic_media_route_on_holo_dark" /> - <java-symbol type="layout" name="media_route_chooser_layout" /> - <java-symbol type="layout" name="media_route_list_item_top_header" /> - <java-symbol type="layout" name="media_route_list_item_section_header" /> + <java-symbol type="layout" name="media_route_chooser_dialog" /> + <java-symbol type="layout" name="media_route_controller_dialog" /> <java-symbol type="layout" name="media_route_list_item" /> - <java-symbol type="layout" name="media_route_list_item_checkable" /> - <java-symbol type="layout" name="media_route_list_item_collapse_group" /> + <java-symbol type="id" name="media_route_list" /> + <java-symbol type="id" name="media_route_volume_layout" /> + <java-symbol type="id" name="media_route_volume_slider" /> + <java-symbol type="id" name="media_route_control_frame" /> + <java-symbol type="id" name="media_route_disconnect_button" /> + <java-symbol type="id" name="media_route_extended_settings_button" /> + <java-symbol type="string" name="media_route_chooser_title" /> + <java-symbol type="string" name="media_route_chooser_title_for_remote_display" /> <java-symbol type="string" name="bluetooth_a2dp_audio_route_name" /> <java-symbol type="dimen" name="config_minScalingSpan" /> @@ -1451,7 +1456,6 @@ <java-symbol type="color" name="config_defaultNotificationColor" /> <java-symbol type="color" name="input_method_navigation_guard" /> <java-symbol type="drawable" name="ic_notification_ime_default" /> - <java-symbol type="drawable" name="ic_notify_wifidisplay" /> <java-symbol type="drawable" name="ic_menu_refresh" /> <java-symbol type="drawable" name="stat_notify_car_mode" /> <java-symbol type="drawable" name="stat_notify_disabled" /> @@ -1594,8 +1598,10 @@ <java-symbol type="string" name="vpn_lockdown_error" /> <java-symbol type="string" name="vpn_lockdown_config" /> <java-symbol type="string" name="wallpaper_binding_label" /> - <java-symbol type="string" name="wifi_display_notification_title" /> - <java-symbol type="string" name="wifi_display_notification_message" /> + <java-symbol type="string" name="wifi_display_notification_connecting_title" /> + <java-symbol type="string" name="wifi_display_notification_connecting_message" /> + <java-symbol type="string" name="wifi_display_notification_connected_title" /> + <java-symbol type="string" name="wifi_display_notification_connected_message" /> <java-symbol type="string" name="wifi_display_notification_disconnect" /> <java-symbol type="style" name="Theme.Dialog.AppError" /> <java-symbol type="style" name="Theme.Toast" /> diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml index 7af3b9c..3215e17 100644 --- a/core/res/res/xml/power_profile.xml +++ b/core/res/res/xml/power_profile.xml @@ -58,4 +58,12 @@ </array> <!-- This is the battery capacity in mAh (measured at nominal voltage) --> <item name="battery.capacity">1000</item> + + <array name="wifi.batchedscan"> <!-- mA --> + <value>.0002</value> <!-- 1-8/hr --> + <value>.002</value> <!-- 9-64/hr --> + <value>.02</value> <!-- 65-512/hr --> + <value>.2</value> <!-- 513-4,096/hr --> + <value>2</value> <!-- 4097-/hr --> + </array> </device> diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java index 76b702e..4a58f88 100644 --- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java +++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/BandwidthTest.java @@ -36,8 +36,6 @@ import com.android.bandwidthtest.util.BandwidthTestUtil; import com.android.bandwidthtest.util.ConnectionUtil; import java.io.File; -import java.util.HashMap; -import java.util.Map; /** * Test that downloads files from a test server and reports the bandwidth metrics collected. @@ -131,8 +129,8 @@ public class BandwidthTest extends InstrumentationTestCase { results.putString("device_id", mDeviceId); results.putString("timestamp", ts); results.putInt("size", FILE_SIZE); - AddStatsToResults(PROF_LABEL, prof_stats, results); - AddStatsToResults(PROC_LABEL, proc_stats, results); + addStatsToResults(PROF_LABEL, prof_stats, results, mUid); + addStatsToResults(PROC_LABEL, proc_stats, results, mUid); getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results); // Clean up. @@ -185,8 +183,8 @@ public class BandwidthTest extends InstrumentationTestCase { results.putString("device_id", mDeviceId); results.putString("timestamp", ts); results.putInt("size", FILE_SIZE); - AddStatsToResults(PROF_LABEL, prof_stats, results); - AddStatsToResults(PROC_LABEL, proc_stats, results); + addStatsToResults(PROF_LABEL, prof_stats, results, mUid); + addStatsToResults(PROC_LABEL, proc_stats, results, mUid); getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results); // Clean up. @@ -242,8 +240,9 @@ public class BandwidthTest extends InstrumentationTestCase { results.putString("device_id", mDeviceId); results.putString("timestamp", ts); results.putInt("size", FILE_SIZE); - AddStatsToResults(PROF_LABEL, prof_stats, results); - AddStatsToResults(PROC_LABEL, proc_stats, results); + addStatsToResults(PROF_LABEL, prof_stats, results, mUid); + // remember to use download manager uid for proc stats + addStatsToResults(PROC_LABEL, proc_stats, results, downloadManagerUid); getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, results); // Clean up. @@ -302,46 +301,35 @@ public class BandwidthTest extends InstrumentationTestCase { * @param label to attach to this given stats. * @param stats {@link NetworkStats} to add. * @param results {@link Bundle} to be added to. + * @param uid for which to report the results. */ - public void AddStatsToResults(String label, NetworkStats stats, Bundle results){ + public void addStatsToResults(String label, NetworkStats stats, Bundle results, int uid){ if (results == null || results.isEmpty()) { Log.e(LOG_TAG, "Empty bundle provided."); return; } - // Merge stats across all sets. - Map<Integer, Entry> totalStats = new HashMap<Integer, Entry>(); + Entry totalStats = null; for (int i = 0; i < stats.size(); ++i) { Entry statsEntry = stats.getValues(i, null); // We are only interested in the all inclusive stats. if (statsEntry.tag != 0) { continue; } - Entry mapEntry = null; - if (totalStats.containsKey(statsEntry.uid)) { - mapEntry = totalStats.get(statsEntry.uid); - switch (statsEntry.set) { - case NetworkStats.SET_ALL: - mapEntry.rxBytes = statsEntry.rxBytes; - mapEntry.txBytes = statsEntry.txBytes; - break; - case NetworkStats.SET_DEFAULT: - case NetworkStats.SET_FOREGROUND: - mapEntry.rxBytes += statsEntry.rxBytes; - mapEntry.txBytes += statsEntry.txBytes; - break; - default: - Log.w(LOG_TAG, "Invalid state found in NetworkStats."); - } + // skip stats for other uids + if (statsEntry.uid != uid) { + continue; + } + if (totalStats == null || statsEntry.set == NetworkStats.SET_ALL) { + totalStats = statsEntry; } else { - totalStats.put(statsEntry.uid, statsEntry); + totalStats.rxBytes += statsEntry.rxBytes; + totalStats.txBytes += statsEntry.txBytes; } } - // Ouput merged stats to bundle. - for (Entry entry : totalStats.values()) { - results.putInt(label + "uid", entry.uid); - results.putLong(label + "tx", entry.txBytes); - results.putLong(label + "rx", entry.rxBytes); - } + // Output merged stats to bundle. + results.putInt(label + "uid", totalStats.uid); + results.putLong(label + "tx", totalStats.txBytes); + results.putLong(label + "rx", totalStats.rxBytes); } /** diff --git a/data/sounds/AudioPackage10.mk b/data/sounds/AudioPackage10.mk index 783e1f8..ae4bc88 100644 --- a/data/sounds/AudioPackage10.mk +++ b/data/sounds/AudioPackage10.mk @@ -17,19 +17,19 @@ PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/alarms/ogg/Osmium.ogg:system/media/audio/alarms/Osmium.ogg \ $(LOCAL_PATH)/alarms/ogg/Platinum.ogg:system/media/audio/alarms/Platinum.ogg \ $(LOCAL_PATH)/effects/ogg/Effect_Tick_48k.ogg:system/media/audio/ui/Effect_Tick.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressStandard_120_48k.ogg:system/media/audio/ui/KeypressStandard.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressSpacebar_120_48k.ogg:system/media/audio/ui/KeypressSpacebar.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressDelete_120_48k.ogg:system/media/audio/ui/KeypressDelete.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressInvalid_120_48k.ogg:system/media/audio/ui/KeypressInvalid.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressReturn_120_48k.ogg:system/media/audio/ui/KeypressReturn.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressStandard_48k.ogg:system/media/audio/ui/KeypressStandard.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressSpacebar_48k.ogg:system/media/audio/ui/KeypressSpacebar.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressDelete_48k.ogg:system/media/audio/ui/KeypressDelete.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressInvalid_48k.ogg:system/media/audio/ui/KeypressInvalid.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressReturn_48k.ogg:system/media/audio/ui/KeypressReturn.ogg \ $(LOCAL_PATH)/effects/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \ $(LOCAL_PATH)/effects/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg \ $(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \ $(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \ $(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \ $(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \ - $(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \ - $(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \ + $(LOCAL_PATH)/effects/ogg/Lock_48k.ogg:system/media/audio/ui/Lock.ogg \ + $(LOCAL_PATH)/effects/ogg/Unlock_48k.ogg:system/media/audio/ui/Unlock.ogg \ $(LOCAL_PATH)/effects/ogg/WirelessChargingStarted.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \ $(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \ $(LOCAL_PATH)/notifications/ogg/Alya.ogg:system/media/audio/notifications/Alya.ogg \ diff --git a/data/sounds/AudioPackage11.mk b/data/sounds/AudioPackage11.mk index b30be56..3c09297 100644 --- a/data/sounds/AudioPackage11.mk +++ b/data/sounds/AudioPackage11.mk @@ -17,19 +17,19 @@ PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/alarms/ogg/Osmium.ogg:system/media/audio/alarms/Osmium.ogg \ $(LOCAL_PATH)/alarms/ogg/Platinum.ogg:system/media/audio/alarms/Platinum.ogg \ $(LOCAL_PATH)/effects/ogg/Effect_Tick_48k.ogg:system/media/audio/ui/Effect_Tick.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressStandard_120_48k.ogg:system/media/audio/ui/KeypressStandard.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressSpacebar_120_48k.ogg:system/media/audio/ui/KeypressSpacebar.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressDelete_120_48k.ogg:system/media/audio/ui/KeypressDelete.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressInvalid_120_48k.ogg:system/media/audio/ui/KeypressInvalid.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressReturn_120_48k.ogg:system/media/audio/ui/KeypressReturn.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressStandard_48k.ogg:system/media/audio/ui/KeypressStandard.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressSpacebar_48k.ogg:system/media/audio/ui/KeypressSpacebar.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressDelete_48k.ogg:system/media/audio/ui/KeypressDelete.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressInvalid_48k.ogg:system/media/audio/ui/KeypressInvalid.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressReturn_48k.ogg:system/media/audio/ui/KeypressReturn.ogg \ $(LOCAL_PATH)/effects/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \ $(LOCAL_PATH)/effects/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg \ $(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \ $(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \ $(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \ $(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \ - $(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \ - $(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \ + $(LOCAL_PATH)/effects/ogg/Lock_48k.ogg:system/media/audio/ui/Lock.ogg \ + $(LOCAL_PATH)/effects/ogg/Unlock_48k.ogg:system/media/audio/ui/Unlock.ogg \ $(LOCAL_PATH)/effects/ogg/WirelessChargingStarted.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \ $(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \ $(LOCAL_PATH)/notifications/ogg/Alya.ogg:system/media/audio/notifications/Alya.ogg \ diff --git a/data/sounds/AudioPackage8.mk b/data/sounds/AudioPackage8.mk index 49b6154..0f4b8ad 100644 --- a/data/sounds/AudioPackage8.mk +++ b/data/sounds/AudioPackage8.mk @@ -17,11 +17,11 @@ PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/alarms/ogg/Plutonium.ogg:system/media/audio/alarms/Plutonium.ogg \ $(LOCAL_PATH)/alarms/ogg/Promethium.ogg:system/media/audio/alarms/Promethium.ogg \ $(LOCAL_PATH)/effects/ogg/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressStandard_120.ogg:system/media/audio/ui/KeypressStandard.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressSpacebar_120.ogg:system/media/audio/ui/KeypressSpacebar.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressDelete_120.ogg:system/media/audio/ui/KeypressDelete.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressInvalid_120.ogg:system/media/audio/ui/KeypressInvalid.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressReturn_120.ogg:system/media/audio/ui/KeypressReturn.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \ $(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \ $(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \ $(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \ diff --git a/data/sounds/AudioPackage9.mk b/data/sounds/AudioPackage9.mk index 87b7764..36dc921 100644 --- a/data/sounds/AudioPackage9.mk +++ b/data/sounds/AudioPackage9.mk @@ -17,11 +17,11 @@ PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/alarms/ogg/Osmium.ogg:system/media/audio/alarms/Osmium.ogg \ $(LOCAL_PATH)/alarms/ogg/Platinum.ogg:system/media/audio/alarms/Platinum.ogg \ $(LOCAL_PATH)/effects/ogg/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressStandard_120.ogg:system/media/audio/ui/KeypressStandard.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressSpacebar_120.ogg:system/media/audio/ui/KeypressSpacebar.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressDelete_120.ogg:system/media/audio/ui/KeypressDelete.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressInvalid_120.ogg:system/media/audio/ui/KeypressInvalid.ogg \ - $(LOCAL_PATH)/effects/ogg/KeypressReturn_120.ogg:system/media/audio/ui/KeypressReturn.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \ + $(LOCAL_PATH)/effects/ogg/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \ $(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \ $(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \ $(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \ diff --git a/data/sounds/notifications/ogg/Tethys_48k.ogg b/data/sounds/notifications/ogg/Tethys_48k.ogg Binary files differindex a9d8bbd..355d522 100644 --- a/data/sounds/notifications/ogg/Tethys_48k.ogg +++ b/data/sounds/notifications/ogg/Tethys_48k.ogg diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index af8441a..aac7876 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -88,9 +88,10 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { @Override public boolean getPadding(Rect padding) { final Rect r = mDrawableContainerState.getConstantPadding(); - boolean result = true; + boolean result; if (r != null) { padding.set(r); + result = (r.left | r.top | r.bottom | r.right) != 0; } else { if (mCurrDrawable != null) { result = mCurrDrawable.getPadding(padding); diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java index ab34c0f..9c57a2c 100644 --- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java +++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java @@ -244,7 +244,7 @@ public class NinePatchDrawable extends Drawable { } else { padding.set(mPadding); } - return true; + return (padding.left | padding.top | padding.right | padding.bottom) != 0; } /** diff --git a/media/java/android/media/IMediaRouterClient.aidl b/media/java/android/media/IMediaRouterClient.aidl new file mode 100644 index 0000000..9640dcb --- /dev/null +++ b/media/java/android/media/IMediaRouterClient.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2013 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.media; + +/** + * {@hide} + */ +oneway interface IMediaRouterClient { + void onStateChanged(); +} diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl new file mode 100644 index 0000000..f8f5fdf --- /dev/null +++ b/media/java/android/media/IMediaRouterService.aidl @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2013 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.media; + +import android.media.IMediaRouterClient; +import android.media.MediaRouterClientState; + +/** + * {@hide} + */ +interface IMediaRouterService { + void registerClientAsUser(IMediaRouterClient client, String packageName, int userId); + void unregisterClient(IMediaRouterClient client); + + MediaRouterClientState getState(IMediaRouterClient client); + + void setDiscoveryRequest(IMediaRouterClient client, int routeTypes, boolean activeScan); + void setSelectedRoute(IMediaRouterClient client, String routeId, boolean explicit); + void requestSetVolume(IMediaRouterClient client, String routeId, int volume); + void requestUpdateVolume(IMediaRouterClient client, String routeId, int direction); +} diff --git a/media/java/android/media/IRemoteDisplayCallback.aidl b/media/java/android/media/IRemoteDisplayCallback.aidl new file mode 100644 index 0000000..19cf070 --- /dev/null +++ b/media/java/android/media/IRemoteDisplayCallback.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2013 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.media; + +import android.media.RemoteDisplayState; + +/** + * {@hide} + */ +oneway interface IRemoteDisplayCallback { + void onStateChanged(in RemoteDisplayState state); +} diff --git a/media/java/android/media/IRemoteDisplayProvider.aidl b/media/java/android/media/IRemoteDisplayProvider.aidl new file mode 100644 index 0000000..b0d7379 --- /dev/null +++ b/media/java/android/media/IRemoteDisplayProvider.aidl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2013 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.media; + +import android.media.IRemoteDisplayCallback; + +/** + * {@hide} + */ +oneway interface IRemoteDisplayProvider { + void setCallback(in IRemoteDisplayCallback callback); + void setDiscoveryMode(int mode); + void connect(String id); + void disconnect(String id); + void setVolume(String id, int volume); + void adjustVolume(String id, int delta); +} diff --git a/media/java/android/media/MediaFocusControl.java b/media/java/android/media/MediaFocusControl.java index 59d411d..34008bb 100644 --- a/media/java/android/media/MediaFocusControl.java +++ b/media/java/android/media/MediaFocusControl.java @@ -1930,7 +1930,6 @@ public class MediaFocusControl implements OnFinished { int rccId = RemoteControlClient.RCSE_ID_UNREGISTERED; synchronized(mAudioFocusLock) { synchronized(mRCStack) { - boolean wasCurrentRcController = isCurrentRcController(mediaIntent); // store the new display information try { for (int index = mRCStack.size()-1; index >= 0; index--) { @@ -1977,9 +1976,9 @@ public class MediaFocusControl implements OnFinished { Log.e(TAG, "Wrong index accessing RC stack, lock error? ", e); } - // if the eventReceiver is now at the top of the stack but wasn't before + // if the eventReceiver is at the top of the stack // then check for potential refresh of the remote controls - if (isCurrentRcController(mediaIntent) && !wasCurrentRcController) { + if (isCurrentRcController(mediaIntent)) { checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL); } }//synchronized(mRCStack) diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java index 9a79c94..525dc4f 100644 --- a/media/java/android/media/MediaRouter.java +++ b/media/java/android/media/MediaRouter.java @@ -16,11 +16,15 @@ package android.media; +import com.android.internal.util.Objects; + +import android.Manifest; import android.app.ActivityThread; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManager; @@ -28,8 +32,10 @@ import android.hardware.display.WifiDisplay; import android.hardware.display.WifiDisplayStatus; import android.os.Handler; import android.os.IBinder; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; import android.view.Display; @@ -52,14 +58,17 @@ import java.util.concurrent.CopyOnWriteArrayList; */ public class MediaRouter { private static final String TAG = "MediaRouter"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); static class Static implements DisplayManager.DisplayListener { // Time between wifi display scans when actively scanning in milliseconds. - private static final int WIFI_DISPLAY_SCAN_INTERVAL = 15000; + private static final int WIFI_DISPLAY_SCAN_INTERVAL = 10000; + final Context mAppContext; final Resources mResources; final IAudioService mAudioService; final DisplayManager mDisplayService; + final IMediaRouterService mMediaRouterService; final Handler mHandler; final CopyOnWriteArrayList<CallbackInfo> mCallbacks = new CopyOnWriteArrayList<CallbackInfo>(); @@ -76,9 +85,16 @@ public class MediaRouter { RouteInfo mSelectedRoute; - WifiDisplayStatus mLastKnownWifiDisplayStatus; + final boolean mCanConfigureWifiDisplays; boolean mActivelyScanningWifiDisplays; + int mDiscoveryRequestRouteTypes; + boolean mDiscoverRequestActiveScan; + + int mCurrentUserId = -1; + IMediaRouterClient mClient; + MediaRouterClientState mClientState; + final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() { @Override public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) { @@ -101,6 +117,7 @@ public class MediaRouter { }; Static(Context appContext) { + mAppContext = appContext; mResources = Resources.getSystem(); mHandler = new Handler(appContext.getMainLooper()); @@ -109,10 +126,20 @@ public class MediaRouter { mDisplayService = (DisplayManager) appContext.getSystemService(Context.DISPLAY_SERVICE); + mMediaRouterService = IMediaRouterService.Stub.asInterface( + ServiceManager.getService(Context.MEDIA_ROUTER_SERVICE)); + mSystemCategory = new RouteCategory( com.android.internal.R.string.default_audio_route_category_name, ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO, false); mSystemCategory.mIsSystem = true; + + // Only the system can configure wifi displays. The display manager + // enforces this with a permission check. Set a flag here so that we + // know whether this process is actually allowed to scan and connect. + mCanConfigureWifiDisplays = appContext.checkPermission( + Manifest.permission.CONFIGURE_WIFI_DISPLAY, + Process.myPid(), Process.myUid()) == PackageManager.PERMISSION_GRANTED; } // Called after sStatic is initialized @@ -120,8 +147,7 @@ public class MediaRouter { mDefaultAudioVideo = new RouteInfo(mSystemCategory); mDefaultAudioVideo.mNameResId = com.android.internal.R.string.default_audio_route_name; mDefaultAudioVideo.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO; - mDefaultAudioVideo.mPresentationDisplay = choosePresentationDisplayForRoute( - mDefaultAudioVideo, getAllPresentationDisplays()); + mDefaultAudioVideo.updatePresentationDisplay(); addRouteStatic(mDefaultAudioVideo); // This will select the active wifi display route if there is one. @@ -146,10 +172,13 @@ public class MediaRouter { updateAudioRoutes(newAudioRoutes); } + // Bind to the media router service. + rebindAsUser(UserHandle.myUserId()); + // Select the default route if the above didn't sync us up // appropriately with relevant system state. if (mSelectedRoute == null) { - selectRouteStatic(mDefaultAudioVideo.getSupportedTypes(), mDefaultAudioVideo); + selectDefaultRouteStatic(); } } @@ -197,7 +226,7 @@ public class MediaRouter { dispatchRouteChanged(sStatic.mBluetoothA2dpRoute); } } else if (sStatic.mBluetoothA2dpRoute != null) { - removeRoute(sStatic.mBluetoothA2dpRoute); + removeRouteStatic(sStatic.mBluetoothA2dpRoute); sStatic.mBluetoothA2dpRoute = null; } } @@ -205,16 +234,52 @@ public class MediaRouter { if (mBluetoothA2dpRoute != null) { if (mainType != AudioRoutesInfo.MAIN_SPEAKER && mSelectedRoute == mBluetoothA2dpRoute && !a2dpEnabled) { - selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo); + selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo, false); } else if ((mSelectedRoute == mDefaultAudioVideo || mSelectedRoute == null) && a2dpEnabled) { - selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute); + selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute, false); } } } - void updateActiveScan() { - if (hasActiveScanCallbackOfType(ROUTE_TYPE_LIVE_VIDEO)) { + void updateDiscoveryRequest() { + // What are we looking for today? + int routeTypes = 0; + int passiveRouteTypes = 0; + boolean activeScan = false; + boolean activeScanWifiDisplay = false; + final int count = mCallbacks.size(); + for (int i = 0; i < count; i++) { + CallbackInfo cbi = mCallbacks.get(i); + if ((cbi.flags & (CALLBACK_FLAG_PERFORM_ACTIVE_SCAN + | CALLBACK_FLAG_REQUEST_DISCOVERY)) != 0) { + // Discovery explicitly requested. + routeTypes |= cbi.type; + } else if ((cbi.flags & CALLBACK_FLAG_PASSIVE_DISCOVERY) != 0) { + // Discovery only passively requested. + passiveRouteTypes |= cbi.type; + } else { + // Legacy case since applications don't specify the discovery flag. + // Unfortunately we just have to assume they always need discovery + // whenever they have a callback registered. + routeTypes |= cbi.type; + } + if ((cbi.flags & CALLBACK_FLAG_PERFORM_ACTIVE_SCAN) != 0) { + activeScan = true; + if ((cbi.type & ROUTE_TYPE_REMOTE_DISPLAY) != 0) { + activeScanWifiDisplay = true; + } + } + } + if (routeTypes != 0 || activeScan) { + // If someone else requests discovery then enable the passive listeners. + // This is used by the MediaRouteButton and MediaRouteActionProvider since + // they don't receive lifecycle callbacks from the Activity. + routeTypes |= passiveRouteTypes; + } + + // Update wifi display scanning. + if (activeScanWifiDisplay && mCanConfigureWifiDisplays) { if (!mActivelyScanningWifiDisplays) { mActivelyScanningWifiDisplays = true; mHandler.post(mScanWifiDisplays); @@ -225,18 +290,14 @@ public class MediaRouter { mHandler.removeCallbacks(mScanWifiDisplays); } } - } - private boolean hasActiveScanCallbackOfType(int type) { - final int count = mCallbacks.size(); - for (int i = 0; i < count; i++) { - CallbackInfo cbi = mCallbacks.get(i); - if ((cbi.flags & CALLBACK_FLAG_PERFORM_ACTIVE_SCAN) != 0 - && (cbi.type & type) != 0) { - return true; - } + // Tell the media router service all about it. + if (routeTypes != mDiscoveryRequestRouteTypes + || activeScan != mDiscoverRequestActiveScan) { + mDiscoveryRequestRouteTypes = routeTypes; + mDiscoverRequestActiveScan = activeScan; + publishClientDiscoveryRequest(); } - return false; } @Override @@ -259,17 +320,267 @@ public class MediaRouter { } private void updatePresentationDisplays(int changedDisplayId) { - final Display[] displays = getAllPresentationDisplays(); final int count = mRoutes.size(); for (int i = 0; i < count; i++) { - final RouteInfo info = mRoutes.get(i); - Display display = choosePresentationDisplayForRoute(info, displays); - if (display != info.mPresentationDisplay - || (display != null && display.getDisplayId() == changedDisplayId)) { - info.mPresentationDisplay = display; - dispatchRoutePresentationDisplayChanged(info); + final RouteInfo route = mRoutes.get(i); + if (route.updatePresentationDisplay() || (route.mPresentationDisplay != null + && route.mPresentationDisplay.getDisplayId() == changedDisplayId)) { + dispatchRoutePresentationDisplayChanged(route); + } + } + } + + void setSelectedRoute(RouteInfo info, boolean explicit) { + // Must be non-reentrant. + mSelectedRoute = info; + publishClientSelectedRoute(explicit); + } + + void rebindAsUser(int userId) { + if (mCurrentUserId != userId || userId < 0 || mClient == null) { + if (mClient != null) { + try { + mMediaRouterService.unregisterClient(mClient); + } catch (RemoteException ex) { + Log.e(TAG, "Unable to unregister media router client.", ex); + } + mClient = null; + } + + mCurrentUserId = userId; + + try { + Client client = new Client(); + mMediaRouterService.registerClientAsUser(client, + mAppContext.getPackageName(), userId); + mClient = client; + } catch (RemoteException ex) { + Log.e(TAG, "Unable to register media router client.", ex); + } + + publishClientDiscoveryRequest(); + publishClientSelectedRoute(false); + updateClientState(); + } + } + + void publishClientDiscoveryRequest() { + if (mClient != null) { + try { + mMediaRouterService.setDiscoveryRequest(mClient, + mDiscoveryRequestRouteTypes, mDiscoverRequestActiveScan); + } catch (RemoteException ex) { + Log.e(TAG, "Unable to publish media router client discovery request.", ex); + } + } + } + + void publishClientSelectedRoute(boolean explicit) { + if (mClient != null) { + try { + mMediaRouterService.setSelectedRoute(mClient, + mSelectedRoute != null ? mSelectedRoute.mGlobalRouteId : null, + explicit); + } catch (RemoteException ex) { + Log.e(TAG, "Unable to publish media router client selected route.", ex); + } + } + } + + void updateClientState() { + // Update the client state. + mClientState = null; + if (mClient != null) { + try { + mClientState = mMediaRouterService.getState(mClient); + } catch (RemoteException ex) { + Log.e(TAG, "Unable to retrieve media router client state.", ex); + } + } + final ArrayList<MediaRouterClientState.RouteInfo> globalRoutes = + mClientState != null ? mClientState.routes : null; + final String globallySelectedRouteId = mClientState != null ? + mClientState.globallySelectedRouteId : null; + + // Add or update routes. + final int globalRouteCount = globalRoutes != null ? globalRoutes.size() : 0; + for (int i = 0; i < globalRouteCount; i++) { + final MediaRouterClientState.RouteInfo globalRoute = globalRoutes.get(i); + RouteInfo route = findGlobalRoute(globalRoute.id); + if (route == null) { + route = makeGlobalRoute(globalRoute); + addRouteStatic(route); + } else { + updateGlobalRoute(route, globalRoute); + } + } + + // Synchronize state with the globally selected route. + if (globallySelectedRouteId != null) { + final RouteInfo route = findGlobalRoute(globallySelectedRouteId); + if (route == null) { + Log.w(TAG, "Could not find new globally selected route: " + + globallySelectedRouteId); + } else if (route != mSelectedRoute) { + if (DEBUG) { + Log.d(TAG, "Selecting new globally selected route: " + route); + } + selectRouteStatic(route.mSupportedTypes, route, false); + } + } else if (mSelectedRoute != null && mSelectedRoute.mGlobalRouteId != null) { + if (DEBUG) { + Log.d(TAG, "Unselecting previous globally selected route: " + mSelectedRoute); + } + selectDefaultRouteStatic(); + } + + // Remove defunct routes. + outer: for (int i = mRoutes.size(); i-- > 0; ) { + final RouteInfo route = mRoutes.get(i); + final String globalRouteId = route.mGlobalRouteId; + if (globalRouteId != null) { + for (int j = 0; j < globalRouteCount; j++) { + MediaRouterClientState.RouteInfo globalRoute = globalRoutes.get(j); + if (globalRouteId.equals(globalRoute.id)) { + continue outer; // found + } + } + // not found + removeRouteStatic(route); + } + } + } + + void requestSetVolume(RouteInfo route, int volume) { + if (route.mGlobalRouteId != null && mClient != null) { + try { + mMediaRouterService.requestSetVolume(mClient, + route.mGlobalRouteId, volume); + } catch (RemoteException ex) { + Log.w(TAG, "Unable to request volume change.", ex); + } + } + } + + void requestUpdateVolume(RouteInfo route, int direction) { + if (route.mGlobalRouteId != null && mClient != null) { + try { + mMediaRouterService.requestUpdateVolume(mClient, + route.mGlobalRouteId, direction); + } catch (RemoteException ex) { + Log.w(TAG, "Unable to request volume change.", ex); + } + } + } + + RouteInfo makeGlobalRoute(MediaRouterClientState.RouteInfo globalRoute) { + RouteInfo route = new RouteInfo(sStatic.mSystemCategory); + route.mGlobalRouteId = globalRoute.id; + route.mName = globalRoute.name; + route.mDescription = globalRoute.description; + route.mSupportedTypes = globalRoute.supportedTypes; + route.mEnabled = globalRoute.enabled; + route.setRealStatusCode(globalRoute.statusCode); + route.mPlaybackType = globalRoute.playbackType; + route.mPlaybackStream = globalRoute.playbackStream; + route.mVolume = globalRoute.volume; + route.mVolumeMax = globalRoute.volumeMax; + route.mVolumeHandling = globalRoute.volumeHandling; + route.mPresentationDisplayId = globalRoute.presentationDisplayId; + route.updatePresentationDisplay(); + return route; + } + + void updateGlobalRoute(RouteInfo route, MediaRouterClientState.RouteInfo globalRoute) { + boolean changed = false; + boolean volumeChanged = false; + boolean presentationDisplayChanged = false; + + if (!Objects.equal(route.mName, globalRoute.name)) { + route.mName = globalRoute.name; + changed = true; + } + if (!Objects.equal(route.mDescription, globalRoute.description)) { + route.mDescription = globalRoute.description; + changed = true; + } + final int oldSupportedTypes = route.mSupportedTypes; + if (oldSupportedTypes != globalRoute.supportedTypes) { + route.mSupportedTypes = globalRoute.supportedTypes; + changed = true; + } + if (route.mEnabled != globalRoute.enabled) { + route.mEnabled = globalRoute.enabled; + changed = true; + } + if (route.mRealStatusCode != globalRoute.statusCode) { + route.setRealStatusCode(globalRoute.statusCode); + changed = true; + } + if (route.mPlaybackType != globalRoute.playbackType) { + route.mPlaybackType = globalRoute.playbackType; + changed = true; + } + if (route.mPlaybackStream != globalRoute.playbackStream) { + route.mPlaybackStream = globalRoute.playbackStream; + changed = true; + } + if (route.mVolume != globalRoute.volume) { + route.mVolume = globalRoute.volume; + changed = true; + volumeChanged = true; + } + if (route.mVolumeMax != globalRoute.volumeMax) { + route.mVolumeMax = globalRoute.volumeMax; + changed = true; + volumeChanged = true; + } + if (route.mVolumeHandling != globalRoute.volumeHandling) { + route.mVolumeHandling = globalRoute.volumeHandling; + changed = true; + volumeChanged = true; + } + if (route.mPresentationDisplayId != globalRoute.presentationDisplayId) { + route.mPresentationDisplayId = globalRoute.presentationDisplayId; + route.updatePresentationDisplay(); + changed = true; + presentationDisplayChanged = true; + } + + if (changed) { + dispatchRouteChanged(route, oldSupportedTypes); + } + if (volumeChanged) { + dispatchRouteVolumeChanged(route); + } + if (presentationDisplayChanged) { + dispatchRoutePresentationDisplayChanged(route); + } + } + + RouteInfo findGlobalRoute(String globalRouteId) { + final int count = mRoutes.size(); + for (int i = 0; i < count; i++) { + final RouteInfo route = mRoutes.get(i); + if (globalRouteId.equals(route.mGlobalRouteId)) { + return route; } } + return null; + } + + final class Client extends IMediaRouterClient.Stub { + @Override + public void onStateChanged() { + mHandler.post(new Runnable() { + @Override + public void run() { + if (Client.this == mClient) { + updateClientState(); + } + } + }); + } } } @@ -285,7 +596,7 @@ public class MediaRouter { * <p>Once initiated this routing is transparent to the application. All audio * played on the media stream will be routed to the selected destination.</p> */ - public static final int ROUTE_TYPE_LIVE_AUDIO = 0x1; + public static final int ROUTE_TYPE_LIVE_AUDIO = 1 << 0; /** * Route type flag for live video. @@ -302,7 +613,13 @@ public class MediaRouter { * @see RouteInfo#getPresentationDisplay() * @see android.app.Presentation */ - public static final int ROUTE_TYPE_LIVE_VIDEO = 0x2; + public static final int ROUTE_TYPE_LIVE_VIDEO = 1 << 1; + + /** + * Temporary interop constant to identify remote displays. + * @hide To be removed when media router API is updated. + */ + public static final int ROUTE_TYPE_REMOTE_DISPLAY = 1 << 2; /** * Route type flag for application-specific usage. @@ -312,7 +629,10 @@ public class MediaRouter { * is expected to interpret the meaning of these events and perform the requested * routing tasks.</p> */ - public static final int ROUTE_TYPE_USER = 0x00800000; + public static final int ROUTE_TYPE_USER = 1 << 23; + + static final int ROUTE_TYPE_ANY = ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO + | ROUTE_TYPE_REMOTE_DISPLAY | ROUTE_TYPE_USER; /** * Flag for {@link #addCallback}: Actively scan for routes while this callback @@ -336,11 +656,40 @@ public class MediaRouter { * Flag for {@link #addCallback}: Do not filter route events. * <p> * When this flag is specified, the callback will be invoked for event that affect any - * route event if they do not match the callback's associated media route selector. + * route even if they do not match the callback's filter. * </p> */ public static final int CALLBACK_FLAG_UNFILTERED_EVENTS = 1 << 1; + /** + * Explicitly requests discovery. + * + * @hide Future API ported from support library. Revisit this later. + */ + public static final int CALLBACK_FLAG_REQUEST_DISCOVERY = 1 << 2; + + /** + * Requests that discovery be performed but only if there is some other active + * callback already registered. + * + * @hide Compatibility workaround for the fact that applications do not currently + * request discovery explicitly (except when using the support library API). + */ + public static final int CALLBACK_FLAG_PASSIVE_DISCOVERY = 1 << 3; + + /** + * Flag for {@link #isRouteAvailable}: Ignore the default route. + * <p> + * This flag is used to determine whether a matching non-default route is available. + * This constraint may be used to decide whether to offer the route chooser dialog + * to the user. There is no point offering the chooser if there are no + * non-default choices. + * </p> + * + * @hide Future API ported from support library. Revisit this later. + */ + public static final int AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE = 1 << 0; + // Maps application contexts static final HashMap<Context, MediaRouter> sRouters = new HashMap<Context, MediaRouter>(); @@ -352,6 +701,9 @@ public class MediaRouter { if ((types & ROUTE_TYPE_LIVE_VIDEO) != 0) { result.append("ROUTE_TYPE_LIVE_VIDEO "); } + if ((types & ROUTE_TYPE_REMOTE_DISPLAY) != 0) { + result.append("ROUTE_TYPE_REMOTE_DISPLAY "); + } if ((types & ROUTE_TYPE_USER) != 0) { result.append("ROUTE_TYPE_USER "); } @@ -388,6 +740,11 @@ public class MediaRouter { return sStatic.mSystemCategory; } + /** @hide */ + public RouteInfo getSelectedRoute() { + return getSelectedRoute(ROUTE_TYPE_ANY); + } + /** * Return the currently selected route for any of the given types * @@ -411,6 +768,38 @@ public class MediaRouter { } /** + * Returns true if there is a route that matches the specified types. + * <p> + * This method returns true if there are any available routes that match the types + * regardless of whether they are enabled or disabled. If the + * {@link #AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE} flag is specified, then + * the method will only consider non-default routes. + * </p> + * + * @param types The types to match. + * @param flags Flags to control the determination of whether a route may be available. + * May be zero or {@link #AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE}. + * @return True if a matching route may be available. + * + * @hide Future API ported from support library. Revisit this later. + */ + public boolean isRouteAvailable(int types, int flags) { + final int count = sStatic.mRoutes.size(); + for (int i = 0; i < count; i++) { + RouteInfo route = sStatic.mRoutes.get(i); + if (route.matchesTypes(types)) { + if ((flags & AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE) == 0 + || route != sStatic.mDefaultAudioVideo) { + return true; + } + } + } + + // It doesn't look like we can find a matching route right now. + return false; + } + + /** * Add a callback to listen to events about specific kinds of media routes. * If the specified callback is already registered, its registration will be updated for any * additional route types specified. @@ -453,9 +842,7 @@ public class MediaRouter { info = new CallbackInfo(cb, types, flags, this); sStatic.mCallbacks.add(info); } - if ((info.flags & CALLBACK_FLAG_PERFORM_ACTIVE_SCAN) != 0) { - sStatic.updateActiveScan(); - } + sStatic.updateDiscoveryRequest(); } /** @@ -466,10 +853,8 @@ public class MediaRouter { public void removeCallback(Callback cb) { int index = findCallbackInfo(cb); if (index >= 0) { - CallbackInfo info = sStatic.mCallbacks.remove(index); - if ((info.flags & CALLBACK_FLAG_PERFORM_ACTIVE_SCAN) != 0) { - sStatic.updateActiveScan(); - } + sStatic.mCallbacks.remove(index); + sStatic.updateDiscoveryRequest(); } else { Log.w(TAG, "removeCallback(" + cb + "): callback not registered"); } @@ -499,20 +884,20 @@ public class MediaRouter { * @param route Route to select */ public void selectRoute(int types, RouteInfo route) { - selectRouteStatic(types, route); + selectRouteStatic(types, route, true); } - + /** * @hide internal use */ - public void selectRouteInt(int types, RouteInfo route) { - selectRouteStatic(types, route); + public void selectRouteInt(int types, RouteInfo route, boolean explicit) { + selectRouteStatic(types, route, explicit); } - static void selectRouteStatic(int types, RouteInfo route) { + static void selectRouteStatic(int types, RouteInfo route, boolean explicit) { final RouteInfo oldRoute = sStatic.mSelectedRoute; if (oldRoute == route) return; - if ((route.getSupportedTypes() & types) == 0) { + if (!route.matchesTypes(types)) { Log.w(TAG, "selectRoute ignored; cannot select route with supported types " + typesToString(route.getSupportedTypes()) + " into route types " + typesToString(types)); @@ -535,21 +920,43 @@ public class MediaRouter { final boolean newRouteHasAddress = route != null && route.mDeviceAddress != null; if (activeDisplay != null || oldRouteHasAddress || newRouteHasAddress) { if (newRouteHasAddress && !matchesDeviceAddress(activeDisplay, route)) { - sStatic.mDisplayService.connectWifiDisplay(route.mDeviceAddress); + if (sStatic.mCanConfigureWifiDisplays) { + sStatic.mDisplayService.connectWifiDisplay(route.mDeviceAddress); + } else { + Log.e(TAG, "Cannot connect to wifi displays because this process " + + "is not allowed to do so."); + } } else if (activeDisplay != null && !newRouteHasAddress) { sStatic.mDisplayService.disconnectWifiDisplay(); } } + sStatic.setSelectedRoute(route, explicit); + if (oldRoute != null) { dispatchRouteUnselected(types & oldRoute.getSupportedTypes(), oldRoute); + if (oldRoute.resolveStatusCode()) { + dispatchRouteChanged(oldRoute); + } } - sStatic.mSelectedRoute = route; if (route != null) { + if (route.resolveStatusCode()) { + dispatchRouteChanged(route); + } dispatchRouteSelected(types & route.getSupportedTypes(), route); } } + static void selectDefaultRouteStatic() { + // TODO: Be smarter about the route types here; this selects for all valid. + if (sStatic.mSelectedRoute != sStatic.mBluetoothA2dpRoute + && sStatic.mBluetoothA2dpRoute != null) { + selectRouteStatic(ROUTE_TYPE_ANY, sStatic.mBluetoothA2dpRoute, false); + } else { + selectRouteStatic(ROUTE_TYPE_ANY, sStatic.mDefaultAudioVideo, false); + } + } + /** * Compare the device address of a display and a route. * Nulls/no device address will match another null/no address. @@ -612,7 +1019,7 @@ public class MediaRouter { * @see #addUserRoute(UserRouteInfo) */ public void removeUserRoute(UserRouteInfo info) { - removeRoute(info); + removeRouteStatic(info); } /** @@ -626,7 +1033,7 @@ public class MediaRouter { // TODO Right now, RouteGroups only ever contain user routes. // The code below will need to change if this assumption does. if (info instanceof UserRouteInfo || info instanceof RouteGroup) { - removeRouteAt(i); + removeRouteStatic(info); i--; } } @@ -636,10 +1043,10 @@ public class MediaRouter { * @hide internal use only */ public void removeRouteInt(RouteInfo info) { - removeRoute(info); + removeRouteStatic(info); } - static void removeRoute(RouteInfo info) { + static void removeRouteStatic(RouteInfo info) { if (sStatic.mRoutes.remove(info)) { final RouteCategory removingCat = info.getCategory(); final int count = sStatic.mRoutes.size(); @@ -651,42 +1058,9 @@ public class MediaRouter { break; } } - if (info == sStatic.mSelectedRoute) { - // Removing the currently selected route? Select the default before we remove it. - // TODO: Be smarter about the route types here; this selects for all valid. - if (info != sStatic.mBluetoothA2dpRoute && sStatic.mBluetoothA2dpRoute != null) { - selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_USER, - sStatic.mBluetoothA2dpRoute); - } else { - selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_USER, - sStatic.mDefaultAudioVideo); - } - } - if (!found) { - sStatic.mCategories.remove(removingCat); - } - dispatchRouteRemoved(info); - } - } - - void removeRouteAt(int routeIndex) { - if (routeIndex >= 0 && routeIndex < sStatic.mRoutes.size()) { - final RouteInfo info = sStatic.mRoutes.remove(routeIndex); - final RouteCategory removingCat = info.getCategory(); - final int count = sStatic.mRoutes.size(); - boolean found = false; - for (int i = 0; i < count; i++) { - final RouteCategory cat = sStatic.mRoutes.get(i).getCategory(); - if (removingCat == cat) { - found = true; - break; - } - } - if (info == sStatic.mSelectedRoute) { + if (info.isSelected()) { // Removing the currently selected route? Select the default before we remove it. - // TODO: Be smarter about the route types here; this selects for all valid. - selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO | ROUTE_TYPE_USER, - sStatic.mDefaultAudioVideo); + selectDefaultRouteStatic(); } if (!found) { sStatic.mCategories.remove(removingCat); @@ -752,7 +1126,7 @@ public class MediaRouter { * * @see #addUserRoute(UserRouteInfo) * @see #removeUserRoute(UserRouteInfo) - * @see #createRouteCategory(CharSequence) + * @see #createRouteCategory(CharSequence, boolean) */ public UserRouteInfo createUserRoute(RouteCategory category) { return new UserRouteInfo(category); @@ -780,6 +1154,23 @@ public class MediaRouter { return new RouteCategory(nameResId, ROUTE_TYPE_USER, isGroupable); } + /** + * Rebinds the media router to handle routes that belong to the specified user. + * Requires the interact across users permission to access the routes of another user. + * <p> + * This method is a complete hack to work around the singleton nature of the + * media router when running inside of singleton processes like QuickSettings. + * This mechanism should be burned to the ground when MediaRouter is redesigned. + * Ideally the current user would be pulled from the Context but we need to break + * down MediaRouter.Static before we can get there. + * </p> + * + * @hide + */ + public void rebindAsUser(int userId) { + sStatic.rebindAsUser(userId); + } + static void updateRoute(final RouteInfo info) { dispatchRouteChanged(info); } @@ -801,10 +1192,34 @@ public class MediaRouter { } static void dispatchRouteChanged(RouteInfo info) { + dispatchRouteChanged(info, info.mSupportedTypes); + } + + static void dispatchRouteChanged(RouteInfo info, int oldSupportedTypes) { + final int newSupportedTypes = info.mSupportedTypes; for (CallbackInfo cbi : sStatic.mCallbacks) { - if (cbi.filterRouteEvent(info)) { + // Reconstruct some of the history for callbacks that may not have observed + // all of the events needed to correctly interpret the current state. + // FIXME: This is a strong signal that we should deprecate route type filtering + // completely in the future because it can lead to inconsistencies in + // applications. + final boolean oldVisibility = cbi.filterRouteEvent(oldSupportedTypes); + final boolean newVisibility = cbi.filterRouteEvent(newSupportedTypes); + if (!oldVisibility && newVisibility) { + cbi.cb.onRouteAdded(cbi.router, info); + if (info.isSelected()) { + cbi.cb.onRouteSelected(cbi.router, newSupportedTypes, info); + } + } + if (oldVisibility || newVisibility) { cbi.cb.onRouteChanged(cbi.router, info); } + if (oldVisibility && !newVisibility) { + if (info.isSelected()) { + cbi.cb.onRouteUnselected(cbi.router, oldSupportedTypes, info); + } + cbi.cb.onRouteRemoved(cbi.router, info); + } } } @@ -875,65 +1290,73 @@ public class MediaRouter { } } - static void updateWifiDisplayStatus(WifiDisplayStatus newStatus) { - final WifiDisplayStatus oldStatus = sStatic.mLastKnownWifiDisplayStatus; - - // TODO Naive implementation. Make this smarter later. + static void updateWifiDisplayStatus(WifiDisplayStatus status) { boolean wantScan = false; - boolean blockScan = false; - WifiDisplay[] oldDisplays = oldStatus != null ? - oldStatus.getDisplays() : WifiDisplay.EMPTY_ARRAY; - WifiDisplay[] newDisplays; + WifiDisplay[] displays; WifiDisplay activeDisplay; - if (newStatus.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON) { - newDisplays = newStatus.getDisplays(); - activeDisplay = newStatus.getActiveDisplay(); + if (status.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON) { + displays = status.getDisplays(); + activeDisplay = status.getActiveDisplay(); + + // Only the system is able to connect to wifi display routes. + // The display manager will enforce this with a permission check but it + // still publishes information about all available displays. + // Filter the list down to just the active display. + if (!sStatic.mCanConfigureWifiDisplays) { + if (activeDisplay != null) { + displays = new WifiDisplay[] { activeDisplay }; + } else { + displays = WifiDisplay.EMPTY_ARRAY; + } + } } else { - newDisplays = WifiDisplay.EMPTY_ARRAY; + displays = WifiDisplay.EMPTY_ARRAY; activeDisplay = null; } - for (int i = 0; i < newDisplays.length; i++) { - final WifiDisplay d = newDisplays[i]; - if (d.isRemembered()) { + // Add or update routes. + for (int i = 0; i < displays.length; i++) { + final WifiDisplay d = displays[i]; + if (shouldShowWifiDisplay(d, activeDisplay)) { RouteInfo route = findWifiDisplayRoute(d); if (route == null) { - route = makeWifiDisplayRoute(d, newStatus); + route = makeWifiDisplayRoute(d, status); addRouteStatic(route); wantScan = true; } else { - updateWifiDisplayRoute(route, d, newStatus); + updateWifiDisplayRoute(route, d, status); } if (d.equals(activeDisplay)) { - selectRouteStatic(route.getSupportedTypes(), route); - - // Don't scan if we're already connected to a wifi display, - // the scanning process can cause a hiccup with some configurations. - blockScan = true; + selectRouteStatic(route.getSupportedTypes(), route, false); } } } - for (int i = 0; i < oldDisplays.length; i++) { - final WifiDisplay d = oldDisplays[i]; - if (d.isRemembered()) { - final WifiDisplay newDisplay = findMatchingDisplay(d, newDisplays); - if (newDisplay == null || !newDisplay.isRemembered()) { - removeRoute(findWifiDisplayRoute(d)); + + // Remove stale routes. + for (int i = sStatic.mRoutes.size(); i-- > 0; ) { + RouteInfo route = sStatic.mRoutes.get(i); + if (route.mDeviceAddress != null) { + WifiDisplay d = findWifiDisplay(displays, route.mDeviceAddress); + if (d == null || !shouldShowWifiDisplay(d, activeDisplay)) { + removeRouteStatic(route); } } } - if (wantScan && !blockScan) { + // Don't scan if we're already connected to a wifi display, + // the scanning process can cause a hiccup with some configurations. + if (wantScan && activeDisplay != null && sStatic.mCanConfigureWifiDisplays) { sStatic.mDisplayService.scanWifiDisplays(); } + } - sStatic.mLastKnownWifiDisplayStatus = newStatus; + private static boolean shouldShowWifiDisplay(WifiDisplay d, WifiDisplay activeDisplay) { + return d.isRemembered() || d.equals(activeDisplay); } static int getWifiDisplayStatusCode(WifiDisplay d, WifiDisplayStatus wfdStatus) { - int newStatus = RouteInfo.STATUS_NONE; - + int newStatus; if (wfdStatus.getScanState() == WifiDisplayStatus.SCAN_STATE_SCANNING) { newStatus = RouteInfo.STATUS_SCANNING; } else if (d.isAvailable()) { @@ -947,7 +1370,7 @@ public class MediaRouter { final int activeState = wfdStatus.getActiveDisplayState(); switch (activeState) { case WifiDisplayStatus.DISPLAY_STATE_CONNECTED: - newStatus = RouteInfo.STATUS_NONE; + newStatus = RouteInfo.STATUS_CONNECTED; break; case WifiDisplayStatus.DISPLAY_STATE_CONNECTING: newStatus = RouteInfo.STATUS_CONNECTING; @@ -968,18 +1391,17 @@ public class MediaRouter { static RouteInfo makeWifiDisplayRoute(WifiDisplay display, WifiDisplayStatus wfdStatus) { final RouteInfo newRoute = new RouteInfo(sStatic.mSystemCategory); newRoute.mDeviceAddress = display.getDeviceAddress(); - newRoute.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO; + newRoute.mSupportedTypes = ROUTE_TYPE_LIVE_AUDIO | ROUTE_TYPE_LIVE_VIDEO + | ROUTE_TYPE_REMOTE_DISPLAY; newRoute.mVolumeHandling = RouteInfo.PLAYBACK_VOLUME_FIXED; newRoute.mPlaybackType = RouteInfo.PLAYBACK_TYPE_REMOTE; - newRoute.setStatusCode(getWifiDisplayStatusCode(display, wfdStatus)); + newRoute.setRealStatusCode(getWifiDisplayStatusCode(display, wfdStatus)); newRoute.mEnabled = isWifiDisplayEnabled(display, wfdStatus); newRoute.mName = display.getFriendlyDisplayName(); newRoute.mDescription = sStatic.mResources.getText( com.android.internal.R.string.wireless_display_route_description); - - newRoute.mPresentationDisplay = choosePresentationDisplayForRoute(newRoute, - sStatic.getAllPresentationDisplays()); + newRoute.updatePresentationDisplay(); return newRoute; } @@ -996,24 +1418,23 @@ public class MediaRouter { changed |= route.mEnabled != enabled; route.mEnabled = enabled; - changed |= route.setStatusCode(getWifiDisplayStatusCode(display, wfdStatus)); + changed |= route.setRealStatusCode(getWifiDisplayStatusCode(display, wfdStatus)); if (changed) { dispatchRouteChanged(route); } - if (!enabled && route == sStatic.mSelectedRoute) { + if (!enabled && route.isSelected()) { // Oops, no longer available. Reselect the default. - final RouteInfo defaultRoute = sStatic.mDefaultAudioVideo; - selectRouteStatic(defaultRoute.getSupportedTypes(), defaultRoute); + selectDefaultRouteStatic(); } } - private static WifiDisplay findMatchingDisplay(WifiDisplay d, WifiDisplay[] displays) { + private static WifiDisplay findWifiDisplay(WifiDisplay[] displays, String deviceAddress) { for (int i = 0; i < displays.length; i++) { - final WifiDisplay other = displays[i]; - if (d.hasSameAddress(other)) { - return other; + final WifiDisplay d = displays[i]; + if (d.getDeviceAddress().equals(deviceAddress)) { + return d; } } return null; @@ -1030,27 +1451,6 @@ public class MediaRouter { return null; } - private static Display choosePresentationDisplayForRoute(RouteInfo route, Display[] displays) { - if ((route.mSupportedTypes & ROUTE_TYPE_LIVE_VIDEO) != 0) { - if (route.mDeviceAddress != null) { - // Find the indicated Wifi display by its address. - for (Display display : displays) { - if (display.getType() == Display.TYPE_WIFI - && route.mDeviceAddress.equals(display.getAddress())) { - return display; - } - } - return null; - } - - if (route == sStatic.mDefaultAudioVideo && displays.length > 0) { - // Choose the first presentation display from the list. - return displays[0]; - } - } - return null; - } - /** * Information about a media route. */ @@ -1071,12 +1471,18 @@ public class MediaRouter { int mPlaybackStream = AudioManager.STREAM_MUSIC; VolumeCallbackInfo mVcb; Display mPresentationDisplay; + int mPresentationDisplayId = -1; String mDeviceAddress; boolean mEnabled = true; + // An id by which the route is known to the media router service. + // Null if this route only exists as an artifact within this process. + String mGlobalRouteId; + // A predetermined connection status that can override mStatus - private int mStatusCode; + private int mRealStatusCode; + private int mResolvedStatusCode; /** @hide */ public static final int STATUS_NONE = 0; /** @hide */ public static final int STATUS_SCANNING = 1; @@ -1084,19 +1490,20 @@ public class MediaRouter { /** @hide */ public static final int STATUS_AVAILABLE = 3; /** @hide */ public static final int STATUS_NOT_AVAILABLE = 4; /** @hide */ public static final int STATUS_IN_USE = 5; + /** @hide */ public static final int STATUS_CONNECTED = 6; private Object mTag; /** * The default playback type, "local", indicating the presentation of the media is happening * on the same device (e.g. a phone, a tablet) as where it is controlled from. - * @see #setPlaybackType(int) + * @see #getPlaybackType() */ public final static int PLAYBACK_TYPE_LOCAL = 0; /** * A playback type indicating the presentation of the media is happening on * a different device (i.e. the remote device) than where it is controlled from. - * @see #setPlaybackType(int) + * @see #getPlaybackType() */ public final static int PLAYBACK_TYPE_REMOTE = 1; /** @@ -1104,12 +1511,13 @@ public class MediaRouter { * controlled from this object. An example of fixed playback volume is a remote player, * playing over HDMI where the user prefers to control the volume on the HDMI sink, rather * than attenuate at the source. - * @see #setVolumeHandling(int) + * @see #getVolumeHandling() */ public final static int PLAYBACK_VOLUME_FIXED = 0; /** * Playback information indicating the playback volume is variable and can be controlled * from this object. + * @see #getVolumeHandling() */ public final static int PLAYBACK_VOLUME_VARIABLE = 1; @@ -1178,38 +1586,71 @@ public class MediaRouter { * Set this route's status by predetermined status code. If the caller * should dispatch a route changed event this call will return true; */ - boolean setStatusCode(int statusCode) { - if (statusCode != mStatusCode) { - mStatusCode = statusCode; - int resId = 0; + boolean setRealStatusCode(int statusCode) { + if (mRealStatusCode != statusCode) { + mRealStatusCode = statusCode; + return resolveStatusCode(); + } + return false; + } + + /** + * Resolves the status code whenever the real status code or selection state + * changes. + */ + boolean resolveStatusCode() { + int statusCode = mRealStatusCode; + if (isSelected()) { switch (statusCode) { - case STATUS_SCANNING: - resId = com.android.internal.R.string.media_route_status_scanning; - break; - case STATUS_CONNECTING: - resId = com.android.internal.R.string.media_route_status_connecting; - break; + // If the route is selected and its status appears to be between states + // then report it as connecting even though it has not yet had a chance + // to officially move into the CONNECTING state. Note that routes in + // the NONE state are assumed to not require an explicit connection + // lifecycle whereas those that are AVAILABLE are assumed to have + // to eventually proceed to CONNECTED. case STATUS_AVAILABLE: - resId = com.android.internal.R.string.media_route_status_available; - break; - case STATUS_NOT_AVAILABLE: - resId = com.android.internal.R.string.media_route_status_not_available; - break; - case STATUS_IN_USE: - resId = com.android.internal.R.string.media_route_status_in_use; + case STATUS_SCANNING: + statusCode = STATUS_CONNECTING; break; } - mStatus = resId != 0 ? sStatic.mResources.getText(resId) : null; - return true; } - return false; + if (mResolvedStatusCode == statusCode) { + return false; + } + + mResolvedStatusCode = statusCode; + int resId; + switch (statusCode) { + case STATUS_SCANNING: + resId = com.android.internal.R.string.media_route_status_scanning; + break; + case STATUS_CONNECTING: + resId = com.android.internal.R.string.media_route_status_connecting; + break; + case STATUS_AVAILABLE: + resId = com.android.internal.R.string.media_route_status_available; + break; + case STATUS_NOT_AVAILABLE: + resId = com.android.internal.R.string.media_route_status_not_available; + break; + case STATUS_IN_USE: + resId = com.android.internal.R.string.media_route_status_in_use; + break; + case STATUS_CONNECTED: + case STATUS_NONE: + default: + resId = 0; + break; + } + mStatus = resId != 0 ? sStatic.mResources.getText(resId) : null; + return true; } /** * @hide */ public int getStatusCode() { - return mStatusCode; + return mResolvedStatusCode; } /** @@ -1219,6 +1660,11 @@ public class MediaRouter { return mSupportedTypes; } + /** @hide */ + public boolean matchesTypes(int types) { + return (mSupportedTypes & types) != 0; + } + /** * @return The group that this route belongs to. */ @@ -1317,9 +1763,7 @@ public class MediaRouter { Log.e(TAG, "Error setting local stream volume", e); } } else { - Log.e(TAG, getClass().getSimpleName() + ".requestSetVolume(): " + - "Non-local volume playback on system route? " + - "Could not request volume change."); + sStatic.requestSetVolume(this, volume); } } @@ -1338,9 +1782,7 @@ public class MediaRouter { Log.e(TAG, "Error setting local stream volume", e); } } else { - Log.e(TAG, getClass().getSimpleName() + ".requestChangeVolume(): " + - "Non-local volume playback on system route? " + - "Could not request volume change."); + sStatic.requestUpdateVolume(this, direction); } } @@ -1402,6 +1844,55 @@ public class MediaRouter { return mPresentationDisplay; } + boolean updatePresentationDisplay() { + Display display = choosePresentationDisplay(); + if (mPresentationDisplay != display) { + mPresentationDisplay = display; + return true; + } + return false; + } + + private Display choosePresentationDisplay() { + if ((mSupportedTypes & ROUTE_TYPE_LIVE_VIDEO) != 0) { + Display[] displays = sStatic.getAllPresentationDisplays(); + + // Ensure that the specified display is valid for presentations. + // This check will normally disallow the default display unless it was + // configured as a presentation display for some reason. + if (mPresentationDisplayId >= 0) { + for (Display display : displays) { + if (display.getDisplayId() == mPresentationDisplayId) { + return display; + } + } + return null; + } + + // Find the indicated Wifi display by its address. + if (mDeviceAddress != null) { + for (Display display : displays) { + if (display.getType() == Display.TYPE_WIFI + && mDeviceAddress.equals(display.getAddress())) { + return display; + } + } + return null; + } + + // For the default route, choose the first presentation display from the list. + if (this == sStatic.mDefaultAudioVideo && displays.length > 0) { + return displays[0]; + } + } + return null; + } + + /** @hide */ + public String getDeviceAddress() { + return mDeviceAddress; + } + /** * Returns true if this route is enabled and may be selected. * @@ -1418,7 +1909,22 @@ public class MediaRouter { * @return True if this route is in the process of connecting. */ public boolean isConnecting() { - return mStatusCode == STATUS_CONNECTING; + return mResolvedStatusCode == STATUS_CONNECTING; + } + + /** @hide */ + public boolean isSelected() { + return this == sStatic.mSelectedRoute; + } + + /** @hide */ + public boolean isDefault() { + return this == sStatic.mDefaultAudioVideo; + } + + /** @hide */ + public void select() { + selectRouteStatic(mSupportedTypes, this, true); } void setStatusInt(CharSequence status) { @@ -1432,6 +1938,7 @@ public class MediaRouter { } final IRemoteVolumeObserver.Stub mRemoteVolObserver = new IRemoteVolumeObserver.Stub() { + @Override public void dispatchRemoteVolumeUpdate(final int direction, final int value) { sStatic.mHandler.post(new Runnable() { @Override @@ -1460,7 +1967,7 @@ public class MediaRouter { ", status=" + getStatus() + ", category=" + getCategory() + ", supportedTypes=" + supportedTypes + - ", presentationDisplay=" + mPresentationDisplay + "}"; + ", presentationDisplay=" + mPresentationDisplay + " }"; } } @@ -1716,6 +2223,7 @@ public class MediaRouter { mVolumeHandling = PLAYBACK_VOLUME_FIXED; } + @Override CharSequence getName(Resources res) { if (mUpdateName) updateName(); return super.getName(res); @@ -1916,7 +2424,7 @@ public class MediaRouter { final int count = mRoutes.size(); if (count == 0) { // Don't keep empty groups in the router. - MediaRouter.removeRoute(this); + MediaRouter.removeRouteStatic(this); return; } @@ -2071,6 +2579,7 @@ public class MediaRouter { return mIsSystem; } + @Override public String toString() { return "RouteCategory{ name=" + mName + " types=" + typesToString(mTypes) + " groupable=" + mGroupable + " }"; @@ -2091,8 +2600,12 @@ public class MediaRouter { } public boolean filterRouteEvent(RouteInfo route) { + return filterRouteEvent(route.mSupportedTypes); + } + + public boolean filterRouteEvent(int supportedTypes) { return (flags & CALLBACK_FLAG_UNFILTERED_EVENTS) != 0 - || (type & route.mSupportedTypes) != 0; + || (type & supportedTypes) != 0; } } diff --git a/media/java/android/media/MediaRouterClientState.aidl b/media/java/android/media/MediaRouterClientState.aidl new file mode 100644 index 0000000..70077119 --- /dev/null +++ b/media/java/android/media/MediaRouterClientState.aidl @@ -0,0 +1,18 @@ +/* Copyright 2013, 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.media; + +parcelable MediaRouterClientState; diff --git a/media/java/android/media/MediaRouterClientState.java b/media/java/android/media/MediaRouterClientState.java new file mode 100644 index 0000000..54b8276 --- /dev/null +++ b/media/java/android/media/MediaRouterClientState.java @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2013 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.media; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; + +/** + * Information available from MediaRouterService about the state perceived by + * a particular client and the routes that are available to it. + * + * Clients must not modify the contents of this object. + * @hide + */ +public final class MediaRouterClientState implements Parcelable { + /** + * A list of all known routes. + */ + public final ArrayList<RouteInfo> routes; + + /** + * The id of the current globally selected route, or null if none. + * Globally selected routes override any other route selections that applications + * may have made. Used for remote displays. + */ + public String globallySelectedRouteId; + + public MediaRouterClientState() { + routes = new ArrayList<RouteInfo>(); + } + + MediaRouterClientState(Parcel src) { + routes = src.createTypedArrayList(RouteInfo.CREATOR); + globallySelectedRouteId = src.readString(); + } + + public RouteInfo getRoute(String id) { + final int count = routes.size(); + for (int i = 0; i < count; i++) { + final RouteInfo route = routes.get(i); + if (route.id.equals(id)) { + return route; + } + } + return null; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeTypedList(routes); + dest.writeString(globallySelectedRouteId); + } + + @Override + public String toString() { + return "MediaRouterClientState{ globallySelectedRouteId=" + + globallySelectedRouteId + ", routes=" + routes.toString() + " }"; + } + + public static final Parcelable.Creator<MediaRouterClientState> CREATOR = + new Parcelable.Creator<MediaRouterClientState>() { + @Override + public MediaRouterClientState createFromParcel(Parcel in) { + return new MediaRouterClientState(in); + } + + @Override + public MediaRouterClientState[] newArray(int size) { + return new MediaRouterClientState[size]; + } + }; + + public static final class RouteInfo implements Parcelable { + public String id; + public String name; + public String description; + public int supportedTypes; + public boolean enabled; + public int statusCode; + public int playbackType; + public int playbackStream; + public int volume; + public int volumeMax; + public int volumeHandling; + public int presentationDisplayId; + + public RouteInfo(String id) { + this.id = id; + enabled = true; + statusCode = MediaRouter.RouteInfo.STATUS_NONE; + playbackType = MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE; + playbackStream = -1; + volumeHandling = MediaRouter.RouteInfo.PLAYBACK_VOLUME_FIXED; + presentationDisplayId = -1; + } + + public RouteInfo(RouteInfo other) { + id = other.id; + name = other.name; + description = other.description; + supportedTypes = other.supportedTypes; + enabled = other.enabled; + statusCode = other.statusCode; + playbackType = other.playbackType; + playbackStream = other.playbackStream; + volume = other.volume; + volumeMax = other.volumeMax; + volumeHandling = other.volumeHandling; + presentationDisplayId = other.presentationDisplayId; + } + + RouteInfo(Parcel in) { + id = in.readString(); + name = in.readString(); + description = in.readString(); + supportedTypes = in.readInt(); + enabled = in.readInt() != 0; + statusCode = in.readInt(); + playbackType = in.readInt(); + playbackStream = in.readInt(); + volume = in.readInt(); + volumeMax = in.readInt(); + volumeHandling = in.readInt(); + presentationDisplayId = in.readInt(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(id); + dest.writeString(name); + dest.writeString(description); + dest.writeInt(supportedTypes); + dest.writeInt(enabled ? 1 : 0); + dest.writeInt(statusCode); + dest.writeInt(playbackType); + dest.writeInt(playbackStream); + dest.writeInt(volume); + dest.writeInt(volumeMax); + dest.writeInt(volumeHandling); + dest.writeInt(presentationDisplayId); + } + + @Override + public String toString() { + return "RouteInfo{ id=" + id + + ", name=" + name + + ", description=" + description + + ", supportedTypes=0x" + Integer.toHexString(supportedTypes) + + ", enabled=" + enabled + + ", statusCode=" + statusCode + + ", playbackType=" + playbackType + + ", playbackStream=" + playbackStream + + ", volume=" + volume + + ", volumeMax=" + volumeMax + + ", volumeHandling=" + volumeHandling + + ", presentationDisplayId=" + presentationDisplayId + + " }"; + } + + @SuppressWarnings("hiding") + public static final Parcelable.Creator<RouteInfo> CREATOR = + new Parcelable.Creator<RouteInfo>() { + @Override + public RouteInfo createFromParcel(Parcel in) { + return new RouteInfo(in); + } + + @Override + public RouteInfo[] newArray(int size) { + return new RouteInfo[size]; + } + }; + } +} diff --git a/media/java/android/media/RemoteDisplayState.aidl b/media/java/android/media/RemoteDisplayState.aidl new file mode 100644 index 0000000..b3262fc --- /dev/null +++ b/media/java/android/media/RemoteDisplayState.aidl @@ -0,0 +1,18 @@ +/* Copyright 2013, 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.media; + +parcelable RemoteDisplayState; diff --git a/media/java/android/media/RemoteDisplayState.java b/media/java/android/media/RemoteDisplayState.java new file mode 100644 index 0000000..1197f65 --- /dev/null +++ b/media/java/android/media/RemoteDisplayState.java @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2013 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.media; + +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import java.util.ArrayList; + +/** + * Information available from IRemoteDisplayProvider about available remote displays. + * + * Clients must not modify the contents of this object. + * @hide + */ +public final class RemoteDisplayState implements Parcelable { + // Note: These constants are used by the remote display provider API. + // Do not change them! + public static final String SERVICE_INTERFACE = + "com.android.media.remotedisplay.RemoteDisplayProvider"; + public static final int DISCOVERY_MODE_NONE = 0; + public static final int DISCOVERY_MODE_PASSIVE = 1; + public static final int DISCOVERY_MODE_ACTIVE = 2; + + /** + * A list of all remote displays. + */ + public final ArrayList<RemoteDisplayInfo> displays; + + public RemoteDisplayState() { + displays = new ArrayList<RemoteDisplayInfo>(); + } + + RemoteDisplayState(Parcel src) { + displays = src.createTypedArrayList(RemoteDisplayInfo.CREATOR); + } + + public boolean isValid() { + if (displays == null) { + return false; + } + final int count = displays.size(); + for (int i = 0; i < count; i++) { + if (!displays.get(i).isValid()) { + return false; + } + } + return true; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeTypedList(displays); + } + + public static final Parcelable.Creator<RemoteDisplayState> CREATOR = + new Parcelable.Creator<RemoteDisplayState>() { + @Override + public RemoteDisplayState createFromParcel(Parcel in) { + return new RemoteDisplayState(in); + } + + @Override + public RemoteDisplayState[] newArray(int size) { + return new RemoteDisplayState[size]; + } + }; + + public static final class RemoteDisplayInfo implements Parcelable { + // Note: These constants are used by the remote display provider API. + // Do not change them! + public static final int STATUS_NOT_AVAILABLE = 0; + public static final int STATUS_IN_USE = 1; + public static final int STATUS_AVAILABLE = 2; + public static final int STATUS_CONNECTING = 3; + public static final int STATUS_CONNECTED = 4; + + public static final int PLAYBACK_VOLUME_VARIABLE = + MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE; + public static final int PLAYBACK_VOLUME_FIXED = + MediaRouter.RouteInfo.PLAYBACK_VOLUME_FIXED; + + public String id; + public String name; + public String description; + public int status; + public int volume; + public int volumeMax; + public int volumeHandling; + public int presentationDisplayId; + + public RemoteDisplayInfo(String id) { + this.id = id; + status = STATUS_NOT_AVAILABLE; + volumeHandling = MediaRouter.RouteInfo.PLAYBACK_VOLUME_FIXED; + presentationDisplayId = -1; + } + + public RemoteDisplayInfo(RemoteDisplayInfo other) { + id = other.id; + name = other.name; + description = other.description; + status = other.status; + volume = other.volume; + volumeMax = other.volumeMax; + volumeHandling = other.volumeHandling; + presentationDisplayId = other.presentationDisplayId; + } + + RemoteDisplayInfo(Parcel in) { + id = in.readString(); + name = in.readString(); + description = in.readString(); + status = in.readInt(); + volume = in.readInt(); + volumeMax = in.readInt(); + volumeHandling = in.readInt(); + presentationDisplayId = in.readInt(); + } + + public boolean isValid() { + return !TextUtils.isEmpty(id) && !TextUtils.isEmpty(name); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(id); + dest.writeString(name); + dest.writeString(description); + dest.writeInt(status); + dest.writeInt(volume); + dest.writeInt(volumeMax); + dest.writeInt(volumeHandling); + dest.writeInt(presentationDisplayId); + } + + @Override + public String toString() { + return "RemoteDisplayInfo{ id=" + id + + ", name=" + name + + ", description=" + description + + ", status=" + status + + ", volume=" + volume + + ", volumeMax=" + volumeMax + + ", volumeHandling=" + volumeHandling + + ", presentationDisplayId=" + presentationDisplayId + + " }"; + } + + @SuppressWarnings("hiding") + public static final Parcelable.Creator<RemoteDisplayInfo> CREATOR = + new Parcelable.Creator<RemoteDisplayInfo>() { + @Override + public RemoteDisplayInfo createFromParcel(Parcel in) { + return new RemoteDisplayInfo(in); + } + + @Override + public RemoteDisplayInfo[] newArray(int size) { + return new RemoteDisplayInfo[size]; + } + }; + } +} diff --git a/media/lib/Android.mk b/media/lib/Android.mk new file mode 100644 index 0000000..50799a6 --- /dev/null +++ b/media/lib/Android.mk @@ -0,0 +1,46 @@ +# +# Copyright (C) 2013 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. +# +LOCAL_PATH := $(call my-dir) + +# the library +# ============================================================ +include $(CLEAR_VARS) + +LOCAL_MODULE:= com.android.media.remotedisplay +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + $(call all-subdir-java-files) \ + $(call all-aidl-files-under, java) + +include $(BUILD_JAVA_LIBRARY) + + +# ==== com.android.media.remotedisplay.xml lib def ======================== +include $(CLEAR_VARS) + +LOCAL_MODULE := com.android.media.remotedisplay.xml +LOCAL_MODULE_TAGS := optional + +LOCAL_MODULE_CLASS := ETC + +# This will install the file in /system/etc/permissions +# +LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions + +LOCAL_SRC_FILES := $(LOCAL_MODULE) + +include $(BUILD_PREBUILT) diff --git a/media/lib/README.txt b/media/lib/README.txt new file mode 100644 index 0000000..cade3df --- /dev/null +++ b/media/lib/README.txt @@ -0,0 +1,28 @@ +This library (com.android.media.remotedisplay.jar) is a shared java library +containing classes required by unbundled remote display providers. + +--- Rules of this library --- +o This library is effectively a PUBLIC API for unbundled remote display providers + that may be distributed outside the system image. So it MUST BE API STABLE. + You can add but not remove. The rules are the same as for the + public platform SDK API. +o This library can see and instantiate internal platform classes, but it must not + expose them in any public method (or by extending them via inheritance). This would + break clients of the library because they cannot see the internal platform classes. + +This library is distributed in the system image, and loaded as +a shared library. So you can change the implementation, but not +the interface. In this way it is like framework.jar. + +--- Why does this library exists? --- + +Unbundled remote display providers (such as Cast) cannot use internal +platform classes. + +This library will eventually be replaced when the media route provider +infrastructure that is currently defined in the support library is reintegrated +with the framework in a new API. That API isn't ready yet so this +library is a compromise to make new capabilities available to the system +without exposing the full surface area of the support library media +route provider protocol. + diff --git a/core/res/res/layout/media_route_list_item_top_header.xml b/media/lib/com.android.media.remotedisplay.xml index 0c49b24..77a91d2 100644 --- a/core/res/res/layout/media_route_list_item_top_header.xml +++ b/media/lib/com.android.media.remotedisplay.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2012 The Android Open Source Project +<!-- Copyright (C) 2013 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. @@ -14,16 +14,7 @@ limitations under the License. --> -<TextView xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@android:id/text1" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceSmall" - android:background="#19ffffff" - android:textStyle="bold" - android:textAllCaps="true" - android:gravity="center_vertical" - android:paddingStart="?android:attr/listPreferredItemPaddingStart" - android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" - android:minHeight="24dp" -/> +<permissions> + <library name="com.android.media.remotedisplay" + file="/system/framework/com.android.media.remotedisplay.jar" /> +</permissions> diff --git a/media/lib/java/com/android/media/remotedisplay/RemoteDisplay.java b/media/lib/java/com/android/media/remotedisplay/RemoteDisplay.java new file mode 100644 index 0000000..5e15702 --- /dev/null +++ b/media/lib/java/com/android/media/remotedisplay/RemoteDisplay.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.media.remotedisplay; + +import com.android.internal.util.Objects; + +import android.media.MediaRouter; +import android.media.RemoteDisplayState.RemoteDisplayInfo; +import android.text.TextUtils; + +/** + * Represents a remote display that has been discovered. + */ +public class RemoteDisplay { + private final RemoteDisplayInfo mMutableInfo; + private RemoteDisplayInfo mImmutableInfo; + + /** + * Status code: Indicates that the remote display is not available. + */ + public static final int STATUS_NOT_AVAILABLE = RemoteDisplayInfo.STATUS_NOT_AVAILABLE; + + /** + * Status code: Indicates that the remote display is in use by someone else. + */ + public static final int STATUS_IN_USE = RemoteDisplayInfo.STATUS_IN_USE; + + /** + * Status code: Indicates that the remote display is available for new connections. + */ + public static final int STATUS_AVAILABLE = RemoteDisplayInfo.STATUS_AVAILABLE; + + /** + * Status code: Indicates that the remote display is current connecting. + */ + public static final int STATUS_CONNECTING = RemoteDisplayInfo.STATUS_CONNECTING; + + /** + * Status code: Indicates that the remote display is connected and is mirroring + * display contents. + */ + public static final int STATUS_CONNECTED = RemoteDisplayInfo.STATUS_CONNECTED; + + /** + * Volume handling: Output volume can be changed. + */ + public static final int PLAYBACK_VOLUME_VARIABLE = + RemoteDisplayInfo.PLAYBACK_VOLUME_VARIABLE; + + /** + * Volume handling: Output volume is fixed. + */ + public static final int PLAYBACK_VOLUME_FIXED = + RemoteDisplayInfo.PLAYBACK_VOLUME_FIXED; + + /** + * Creates a remote display with the specified name and id. + */ + public RemoteDisplay(String id, String name) { + if (TextUtils.isEmpty(id)) { + throw new IllegalArgumentException("id must not be null or empty"); + } + mMutableInfo = new RemoteDisplayInfo(id); + setName(name); + } + + public String getId() { + return mMutableInfo.id; + } + + public String getName() { + return mMutableInfo.name; + } + + public void setName(String name) { + if (!Objects.equal(mMutableInfo.name, name)) { + mMutableInfo.name = name; + mImmutableInfo = null; + } + } + + public String getDescription() { + return mMutableInfo.description; + } + + public void setDescription(String description) { + if (!Objects.equal(mMutableInfo.description, description)) { + mMutableInfo.description = description; + mImmutableInfo = null; + } + } + + public int getStatus() { + return mMutableInfo.status; + } + + public void setStatus(int status) { + if (mMutableInfo.status != status) { + mMutableInfo.status = status; + mImmutableInfo = null; + } + } + + public int getVolume() { + return mMutableInfo.volume; + } + + public void setVolume(int volume) { + if (mMutableInfo.volume != volume) { + mMutableInfo.volume = volume; + mImmutableInfo = null; + } + } + + public int getVolumeMax() { + return mMutableInfo.volumeMax; + } + + public void setVolumeMax(int volumeMax) { + if (mMutableInfo.volumeMax != volumeMax) { + mMutableInfo.volumeMax = volumeMax; + mImmutableInfo = null; + } + } + + public int getVolumeHandling() { + return mMutableInfo.volumeHandling; + } + + public void setVolumeHandling(int volumeHandling) { + if (mMutableInfo.volumeHandling != volumeHandling) { + mMutableInfo.volumeHandling = volumeHandling; + mImmutableInfo = null; + } + } + + public int getPresentationDisplayId() { + return mMutableInfo.presentationDisplayId; + } + + public void setPresentationDisplayId(int presentationDisplayId) { + if (mMutableInfo.presentationDisplayId != presentationDisplayId) { + mMutableInfo.presentationDisplayId = presentationDisplayId; + mImmutableInfo = null; + } + } + + @Override + public String toString() { + return "RemoteDisplay{" + mMutableInfo.toString() + "}"; + } + + RemoteDisplayInfo getInfo() { + if (mImmutableInfo == null) { + mImmutableInfo = new RemoteDisplayInfo(mMutableInfo); + } + return mImmutableInfo; + } +} diff --git a/media/lib/java/com/android/media/remotedisplay/RemoteDisplayProvider.java b/media/lib/java/com/android/media/remotedisplay/RemoteDisplayProvider.java new file mode 100644 index 0000000..e2df77c --- /dev/null +++ b/media/lib/java/com/android/media/remotedisplay/RemoteDisplayProvider.java @@ -0,0 +1,407 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.media.remotedisplay; + +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.media.IRemoteDisplayCallback; +import android.media.IRemoteDisplayProvider; +import android.media.RemoteDisplayState; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.provider.Settings; +import android.util.ArrayMap; + +import java.util.Collection; + +/** + * Base class for remote display providers implemented as unbundled services. + * <p> + * To implement your remote display provider service, create a subclass of + * {@link Service} and override the {@link Service#onBind Service.onBind()} method + * to return the provider's binder when the {@link #SERVICE_INTERFACE} is requested. + * </p> + * <pre> + * public class SampleRemoteDisplayProviderService extends Service { + * private SampleProvider mProvider; + * + * public IBinder onBind(Intent intent) { + * if (intent.getAction().equals(RemoteDisplayProvider.SERVICE_INTERFACE)) { + * if (mProvider == null) { + * mProvider = new SampleProvider(this); + * } + * return mProvider.getBinder(); + * } + * return null; + * } + * + * class SampleProvider extends RemoteDisplayProvider { + * public SampleProvider() { + * super(SampleRemoteDisplayProviderService.this); + * } + * + * // --- Implementation goes here --- + * } + * } + * </pre> + * <p> + * Declare your remote display provider service in your application manifest + * like this: + * </p> + * <pre> + * <application> + * <uses-library android:name="com.android.media.remotedisplay" /> + * + * <service android:name=".SampleRemoteDisplayProviderService" + * android:label="@string/sample_remote_display_provider_service" + * android:exported="true" + * android:permission="android.permission.BIND_REMOTE_DISPLAY"> + * <intent-filter> + * <action android:name="com.android.media.remotedisplay.RemoteDisplayProvider" /> + * </intent-filter> + * </service> + * </application> + * </pre> + * <p> + * This object is not thread safe. It is only intended to be accessed on the + * {@link Context#getMainLooper main looper thread} of an application. + * </p><p> + * IMPORTANT: This class is effectively a public API for unbundled applications, and + * must remain API stable. See README.txt in the root of this package for more information. + * </p> + */ +public abstract class RemoteDisplayProvider { + private static final int MSG_SET_CALLBACK = 1; + private static final int MSG_SET_DISCOVERY_MODE = 2; + private static final int MSG_CONNECT = 3; + private static final int MSG_DISCONNECT = 4; + private static final int MSG_SET_VOLUME = 5; + private static final int MSG_ADJUST_VOLUME = 6; + + private final Context mContext; + private final ProviderStub mStub; + private final ProviderHandler mHandler; + private final ArrayMap<String, RemoteDisplay> mDisplays = + new ArrayMap<String, RemoteDisplay>(); + private IRemoteDisplayCallback mCallback; + private int mDiscoveryMode = DISCOVERY_MODE_NONE; + + private PendingIntent mSettingsPendingIntent; + + /** + * The {@link Intent} that must be declared as handled by the service. + * Put this in your manifest. + */ + public static final String SERVICE_INTERFACE = RemoteDisplayState.SERVICE_INTERFACE; + + /** + * Discovery mode: Do not perform any discovery. + */ + public static final int DISCOVERY_MODE_NONE = RemoteDisplayState.DISCOVERY_MODE_NONE; + + /** + * Discovery mode: Passive or low-power periodic discovery. + * <p> + * This mode indicates that an application is interested in knowing whether there + * are any remote displays paired or available but doesn't need the latest or + * most detailed information. The provider may scan at a lower rate or rely on + * knowledge of previously paired devices. + * </p> + */ + public static final int DISCOVERY_MODE_PASSIVE = RemoteDisplayState.DISCOVERY_MODE_PASSIVE; + + /** + * Discovery mode: Active discovery. + * <p> + * This mode indicates that the user is actively trying to connect to a route + * and we should perform continuous scans. This mode may use significantly more + * power but is intended to be short-lived. + * </p> + */ + public static final int DISCOVERY_MODE_ACTIVE = RemoteDisplayState.DISCOVERY_MODE_ACTIVE; + + /** + * Creates a remote display provider. + * + * @param context The application context for the remote display provider. + */ + public RemoteDisplayProvider(Context context) { + mContext = context; + mStub = new ProviderStub(); + mHandler = new ProviderHandler(context.getMainLooper()); + } + + /** + * Gets the context of the remote display provider. + */ + public final Context getContext() { + return mContext; + } + + /** + * Gets the Binder associated with the provider. + * <p> + * This is intended to be used for the onBind() method of a service that implements + * a remote display provider service. + * </p> + * + * @return The IBinder instance associated with the provider. + */ + public IBinder getBinder() { + return mStub; + } + + /** + * Called when the current discovery mode changes. + * + * @param mode The new discovery mode. + */ + public void onDiscoveryModeChanged(int mode) { + } + + /** + * Called when the system would like to connect to a display. + * + * @param display The remote display. + */ + public void onConnect(RemoteDisplay display) { + } + + /** + * Called when the system would like to disconnect from a display. + * + * @param display The remote display. + */ + public void onDisconnect(RemoteDisplay display) { + } + + /** + * Called when the system would like to set the volume of a display. + * + * @param display The remote display. + * @param volume The desired volume. + */ + public void onSetVolume(RemoteDisplay display, int volume) { + } + + /** + * Called when the system would like to adjust the volume of a display. + * + * @param display The remote display. + * @param delta An increment to add to the current volume, such as +1 or -1. + */ + public void onAdjustVolume(RemoteDisplay display, int delta) { + } + + /** + * Gets the current discovery mode. + * + * @return The current discovery mode. + */ + public int getDiscoveryMode() { + return mDiscoveryMode; + } + + /** + * Gets the current collection of displays. + * + * @return The current collection of displays, which must not be modified. + */ + public Collection<RemoteDisplay> getDisplays() { + return mDisplays.values(); + } + + /** + * Adds the specified remote display and notifies the system. + * + * @param display The remote display that was added. + * @throws IllegalStateException if there is already a display with the same id. + */ + public void addDisplay(RemoteDisplay display) { + if (display == null || mDisplays.containsKey(display.getId())) { + throw new IllegalArgumentException("display"); + } + mDisplays.put(display.getId(), display); + publishState(); + } + + /** + * Updates information about the specified remote display and notifies the system. + * + * @param display The remote display that was added. + * @throws IllegalStateException if the display was n + */ + public void updateDisplay(RemoteDisplay display) { + if (display == null || mDisplays.get(display.getId()) != display) { + throw new IllegalArgumentException("display"); + } + publishState(); + } + + /** + * Removes the specified remote display and tells the system about it. + * + * @param display The remote display that was removed. + */ + public void removeDisplay(RemoteDisplay display) { + if (display == null || mDisplays.get(display.getId()) != display) { + throw new IllegalArgumentException("display"); + } + mDisplays.remove(display.getId()); + publishState(); + } + + /** + * Finds the remote display with the specified id, returns null if not found. + * + * @param id Id of the remote display. + * @return The display, or null if none. + */ + public RemoteDisplay findRemoteDisplay(String id) { + return mDisplays.get(id); + } + + /** + * Gets a pending intent to launch the remote display settings activity. + * + * @return A pending intent to launch the settings activity. + */ + public PendingIntent getSettingsPendingIntent() { + if (mSettingsPendingIntent == null) { + Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS); + settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED + | Intent.FLAG_ACTIVITY_CLEAR_TOP); + mSettingsPendingIntent = PendingIntent.getActivity( + mContext, 0, settingsIntent, 0, null); + } + return mSettingsPendingIntent; + } + + void setCallback(IRemoteDisplayCallback callback) { + mCallback = callback; + publishState(); + } + + void setDiscoveryMode(int mode) { + if (mDiscoveryMode != mode) { + mDiscoveryMode = mode; + onDiscoveryModeChanged(mode); + } + } + + void publishState() { + if (mCallback != null) { + RemoteDisplayState state = new RemoteDisplayState(); + final int count = mDisplays.size(); + for (int i = 0; i < count; i++) { + final RemoteDisplay display = mDisplays.valueAt(i); + state.displays.add(display.getInfo()); + } + try { + mCallback.onStateChanged(state); + } catch (RemoteException ex) { + // system server died? + } + } + } + + final class ProviderStub extends IRemoteDisplayProvider.Stub { + @Override + public void setCallback(IRemoteDisplayCallback callback) { + mHandler.obtainMessage(MSG_SET_CALLBACK, callback).sendToTarget(); + } + + @Override + public void setDiscoveryMode(int mode) { + mHandler.obtainMessage(MSG_SET_DISCOVERY_MODE, mode, 0).sendToTarget(); + } + + @Override + public void connect(String id) { + mHandler.obtainMessage(MSG_CONNECT, id).sendToTarget(); + } + + @Override + public void disconnect(String id) { + mHandler.obtainMessage(MSG_DISCONNECT, id).sendToTarget(); + } + + @Override + public void setVolume(String id, int volume) { + mHandler.obtainMessage(MSG_SET_VOLUME, volume, 0, id).sendToTarget(); + } + + @Override + public void adjustVolume(String id, int delta) { + mHandler.obtainMessage(MSG_ADJUST_VOLUME, delta, 0, id).sendToTarget(); + } + } + + final class ProviderHandler extends Handler { + public ProviderHandler(Looper looper) { + super(looper, null, true); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_SET_CALLBACK: { + setCallback((IRemoteDisplayCallback)msg.obj); + break; + } + case MSG_SET_DISCOVERY_MODE: { + setDiscoveryMode(msg.arg1); + break; + } + case MSG_CONNECT: { + RemoteDisplay display = findRemoteDisplay((String)msg.obj); + if (display != null) { + onConnect(display); + } + break; + } + case MSG_DISCONNECT: { + RemoteDisplay display = findRemoteDisplay((String)msg.obj); + if (display != null) { + onDisconnect(display); + } + break; + } + case MSG_SET_VOLUME: { + RemoteDisplay display = findRemoteDisplay((String)msg.obj); + if (display != null) { + onSetVolume(display, msg.arg1); + } + break; + } + case MSG_ADJUST_VOLUME: { + RemoteDisplay display = findRemoteDisplay((String)msg.obj); + if (display != null) { + onAdjustVolume(display, msg.arg1); + } + break; + } + } + } + } +} diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java b/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java index 55d73f2..1cbc221 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java +++ b/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java @@ -51,7 +51,7 @@ public class FilteringCursorWrapper extends AbstractCursor { mPosition = new int[count]; cursor.moveToPosition(-1); - while (cursor.moveToNext()) { + while (cursor.moveToNext() && mCount < count) { final String mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE); final long lastModified = getCursorLong(cursor, Document.COLUMN_LAST_MODIFIED); if (rejectMimes != null && MimePredicate.mimeMatches(rejectMimes, mimeType)) { diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java index 3a8a3fb..34ce42d 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java @@ -55,6 +55,10 @@ import java.util.concurrent.TimeUnit; public class RecentLoader extends AsyncTaskLoader<DirectoryResult> { private static final boolean LOGD = true; + // TODO: clean up cursor ownership so background thread doesn't traverse + // previously returned cursors for filtering/sorting; this currently races + // with the UI thread. + private static final int MAX_OUTSTANDING_RECENTS = 4; private static final int MAX_OUTSTANDING_RECENTS_SVELTE = 2; diff --git a/packages/ExternalStorageProvider/AndroidManifest.xml b/packages/ExternalStorageProvider/AndroidManifest.xml index 5169fef..edd6255 100644 --- a/packages/ExternalStorageProvider/AndroidManifest.xml +++ b/packages/ExternalStorageProvider/AndroidManifest.xml @@ -3,6 +3,7 @@ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" /> <application android:label="@string/app_label"> <provider diff --git a/packages/FusedLocation/res/values-ca/strings.xml b/packages/FusedLocation/res/values-ca/strings.xml index bdd55dd..9dae512 100644 --- a/packages/FusedLocation/res/values-ca/strings.xml +++ b/packages/FusedLocation/res/values-ca/strings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="5379477904423203699">"Ubicació unificada"</string> + <string name="app_label" msgid="5379477904423203699">"Ubicació combinada"</string> </resources> diff --git a/packages/FusedLocation/res/values-de/strings.xml b/packages/FusedLocation/res/values-de/strings.xml index 0d2cccc..d7e5faa 100644 --- a/packages/FusedLocation/res/values-de/strings.xml +++ b/packages/FusedLocation/res/values-de/strings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="5379477904423203699">"Fused Location"</string> + <string name="app_label" msgid="5379477904423203699">"Kombinierte Standortbestimmung"</string> </resources> diff --git a/packages/FusedLocation/res/values-pl/strings.xml b/packages/FusedLocation/res/values-pl/strings.xml index b3a9e2a..4637034 100644 --- a/packages/FusedLocation/res/values-pl/strings.xml +++ b/packages/FusedLocation/res/values-pl/strings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="5379477904423203699">"Przybliżona lokalizacja"</string> + <string name="app_label" msgid="5379477904423203699">"Uśredniona lokalizacja"</string> </resources> diff --git a/packages/FusedLocation/res/values-pt/strings.xml b/packages/FusedLocation/res/values-pt/strings.xml index cf5f5bf..4f8277a 100644 --- a/packages/FusedLocation/res/values-pt/strings.xml +++ b/packages/FusedLocation/res/values-pt/strings.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_label" msgid="5379477904423203699">"Localização fundida"</string> + <string name="app_label" msgid="5379477904423203699">"Localização combinada"</string> </resources> diff --git a/packages/Keyguard/AndroidManifest.xml b/packages/Keyguard/AndroidManifest.xml index 9e296e2..66d1e75 100644 --- a/packages/Keyguard/AndroidManifest.xml +++ b/packages/Keyguard/AndroidManifest.xml @@ -38,6 +38,7 @@ <uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" /> <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" /> <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" /> + <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" /> <application android:label="@string/app_name" android:process="com.android.systemui" diff --git a/packages/Keyguard/res/layout/keyguard_presentation.xml b/packages/Keyguard/res/layout/keyguard_presentation.xml new file mode 100644 index 0000000..7df0b70 --- /dev/null +++ b/packages/Keyguard/res/layout/keyguard_presentation.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +** +** Copyright 2013, 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. +*/ +--> + +<!-- This is a view that shows general status information in Keyguard. --> +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard" + android:id="@+id/presentation" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <com.android.keyguard.KeyguardStatusView + android:id="@+id/clock" + android:orientation="vertical" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:contentDescription="@string/keyguard_accessibility_status"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal|top" + android:orientation="vertical" + android:focusable="true"> + <TextClock + android:id="@+id/clock_view" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal|top" + android:textColor="@color/clock_white" + android:singleLine="true" + style="@style/widget_big_thin" + android:format12Hour="@string/keyguard_widget_12_hours_format" + android:format24Hour="@string/keyguard_widget_24_hours_format" + android:baselineAligned="true" + android:layout_marginBottom="@dimen/bottom_text_spacing_digital" /> + + <include layout="@layout/keyguard_status_area" /> + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="10dip" + android:layout_gravity="center_horizontal" + android:src="@drawable/kg_security_lock_normal" /> + </LinearLayout> + </com.android.keyguard.KeyguardStatusView> + +</FrameLayout> diff --git a/packages/Keyguard/res/layout/keyguard_status_view.xml b/packages/Keyguard/res/layout/keyguard_status_view.xml index 5857fc2..a4d298a 100644 --- a/packages/Keyguard/res/layout/keyguard_status_view.xml +++ b/packages/Keyguard/res/layout/keyguard_status_view.xml @@ -26,7 +26,7 @@ android:layout_height="match_parent" androidprv:layout_maxWidth="@dimen/keyguard_security_width" androidprv:layout_maxHeight="@dimen/keyguard_security_height" - android:gravity="center_horizontal"> + android:gravity="center"> <com.android.keyguard.KeyguardStatusView android:id="@+id/keyguard_status_view_face_palm" diff --git a/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java b/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java index 3dc4d5c..74e6f33 100644 --- a/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java +++ b/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java @@ -19,7 +19,6 @@ package com.android.keyguard; import android.content.Context; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.Color; -import android.graphics.Paint; import android.graphics.Point; import android.graphics.Rect; import android.os.Handler; @@ -41,7 +40,7 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli private static final String TAG = CameraWidgetFrame.class.getSimpleName(); private static final boolean DEBUG = KeyguardHostView.DEBUG; private static final int WIDGET_ANIMATION_DURATION = 250; // ms - private static final int WIDGET_WAIT_DURATION = 650; // ms + private static final int WIDGET_WAIT_DURATION = 400; // ms private static final int RECOVERY_DELAY = 1000; // ms interface Callbacks { @@ -68,6 +67,7 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli private FixedSizeFrameLayout mPreview; private View mFullscreenPreview; private View mFakeNavBar; + private boolean mUseFastTransition; private final Runnable mTransitionToCameraRunnable = new Runnable() { @Override @@ -418,7 +418,8 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli private void rescheduleTransitionToCamera() { if (DEBUG) Log.d(TAG, "rescheduleTransitionToCamera at " + SystemClock.uptimeMillis()); mHandler.removeCallbacks(mTransitionToCameraRunnable); - mHandler.postDelayed(mTransitionToCameraRunnable, WIDGET_WAIT_DURATION); + final long duration = mUseFastTransition ? 0 : WIDGET_WAIT_DURATION; + mHandler.postDelayed(mTransitionToCameraRunnable, duration); } private void cancelTransitionToCamera() { @@ -513,4 +514,8 @@ public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnCli if (DEBUG) Log.d(TAG, "setInsets: " + insets); mInsets.set(insets); } + + public void setUseFastTransition(boolean useFastTransition) { + mUseFastTransition = useFastTransition; + } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java new file mode 100644 index 0000000..6bcbd6c --- /dev/null +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.keyguard; + +import android.app.Presentation; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnDismissListener; +import android.graphics.Point; +import android.media.MediaRouter; +import android.media.MediaRouter.RouteInfo; +import android.os.Bundle; +import android.util.Slog; +import android.view.Display; +import android.view.View; +import android.view.WindowManager; + +public class KeyguardDisplayManager { + protected static final String TAG = "KeyguardDisplayManager"; + private static boolean DEBUG = KeyguardViewMediator.DEBUG; + Presentation mPresentation; + private MediaRouter mMediaRouter; + private Context mContext; + private boolean mShowing; + + KeyguardDisplayManager(Context context) { + mContext = context; + mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE); + } + + void show() { + if (!mShowing) { + if (DEBUG) Slog.v(TAG, "show"); + mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, + mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY); + updateDisplays(true); + } + mShowing = true; + } + + void hide() { + if (mShowing) { + if (DEBUG) Slog.v(TAG, "hide"); + mMediaRouter.removeCallback(mMediaRouterCallback); + updateDisplays(false); + } + mShowing = false; + } + + private final MediaRouter.SimpleCallback mMediaRouterCallback = + new MediaRouter.SimpleCallback() { + @Override + public void onRouteSelected(MediaRouter router, int type, RouteInfo info) { + if (DEBUG) Slog.d(TAG, "onRouteSelected: type=" + type + ", info=" + info); + updateDisplays(mShowing); + } + + @Override + public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) { + if (DEBUG) Slog.d(TAG, "onRouteUnselected: type=" + type + ", info=" + info); + updateDisplays(mShowing); + } + + @Override + public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo info) { + if (DEBUG) Slog.d(TAG, "onRoutePresentationDisplayChanged: info=" + info); + updateDisplays(mShowing); + } + }; + + private OnDismissListener mOnDismissListener = new OnDismissListener() { + + @Override + public void onDismiss(DialogInterface dialog) { + mPresentation = null; + } + }; + + protected void updateDisplays(boolean showing) { + if (showing) { + MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute( + MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY); + boolean useDisplay = route != null + && route.getPlaybackType() == MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE; + Display presentationDisplay = useDisplay ? route.getPresentationDisplay() : null; + + if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) { + if (DEBUG) Slog.v(TAG, "Display gone: " + mPresentation.getDisplay()); + mPresentation.dismiss(); + mPresentation = null; + } + + if (mPresentation == null && presentationDisplay != null) { + if (DEBUG) Slog.i(TAG, "Keyguard enabled on display: " + presentationDisplay); + mPresentation = new KeyguardPresentation(mContext, presentationDisplay); + mPresentation.setOnDismissListener(mOnDismissListener); + try { + mPresentation.show(); + } catch (WindowManager.InvalidDisplayException ex) { + Slog.w(TAG, "Invalid display:", ex); + mPresentation = null; + } + } + } else { + if (mPresentation != null) { + mPresentation.dismiss(); + mPresentation = null; + } + } + } + + private final static class KeyguardPresentation extends Presentation { + private static final int VIDEO_SAFE_REGION = 80; // Percentage of display width & height + private static final int MOVE_CLOCK_TIMEOUT = 10000; // 10s + private View mClock; + private int mUsableWidth; + private int mUsableHeight; + private int mMarginTop; + private int mMarginLeft; + Runnable mMoveTextRunnable = new Runnable() { + @Override + public void run() { + int x = mMarginLeft + (int) (Math.random() * (mUsableWidth - mClock.getWidth())); + int y = mMarginTop + (int) (Math.random() * (mUsableHeight - mClock.getHeight())); + mClock.setTranslationX(x); + mClock.setTranslationY(y); + mClock.postDelayed(mMoveTextRunnable, MOVE_CLOCK_TIMEOUT); + } + }; + + public KeyguardPresentation(Context context, Display display) { + super(context, display); + getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); + } + + public void onDetachedFromWindow() { + mClock.removeCallbacks(mMoveTextRunnable); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Point p = new Point(); + getDisplay().getSize(p); + mUsableWidth = VIDEO_SAFE_REGION * p.x/100; + mUsableHeight = VIDEO_SAFE_REGION * p.y/100; + mMarginLeft = (100 - VIDEO_SAFE_REGION) * p.x / 200; + mMarginTop = (100 - VIDEO_SAFE_REGION) * p.y / 200; + + setContentView(R.layout.keyguard_presentation); + mClock = findViewById(R.id.clock); + + // Avoid screen burn in + mClock.post(mMoveTextRunnable); + } + } +} diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java index 2719c5c..349078f 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java @@ -60,12 +60,12 @@ import java.util.TimeZone; */ public class KeyguardTransportControlView extends FrameLayout { - private static final int DISPLAY_TIMEOUT_MS = 5000; // 5s private static final int RESET_TO_METADATA_DELAY = 5000; protected static final boolean DEBUG = false; protected static final String TAG = "TransportControlView"; private static final boolean ANIMATE_TRANSITIONS = true; + protected static final long QUIESCENT_PLAYBACK_FACTOR = 1000; private ViewGroup mMetadataContainer; private ViewGroup mInfoContainer; @@ -89,11 +89,9 @@ public class KeyguardTransportControlView extends FrameLayout { private ImageView mBadge; private boolean mSeekEnabled; - private boolean mUserSeeking; private java.text.DateFormat mFormat; - private Date mTimeElapsed; - private Date mTrackDuration; + private Date mTempDate = new Date(); /** * The metadata which should be populated into the view once we've been attached @@ -111,18 +109,25 @@ public class KeyguardTransportControlView extends FrameLayout { @Override public void onClientPlaybackStateUpdate(int state) { - setSeekBarsEnabled(false); updatePlayPauseState(state); } @Override public void onClientPlaybackStateUpdate(int state, long stateChangeTimeMs, long currentPosMs, float speed) { - setSeekBarsEnabled(mMetadata != null && mMetadata.duration > 0); updatePlayPauseState(state); if (DEBUG) Log.d(TAG, "onClientPlaybackStateUpdate(state=" + state + ", stateChangeTimeMs=" + stateChangeTimeMs + ", currentPosMs=" + currentPosMs + ", speed=" + speed + ")"); + + removeCallbacks(mUpdateSeekBars); + // Since the music client may be responding to historical events that cause the + // playback state to change dramatically, wait until things become quiescent before + // resuming automatic scrub position update. + if (mTransientSeek.getVisibility() == View.VISIBLE + && playbackPositionShouldMove(mCurrentPlayState)) { + postDelayed(mUpdateSeekBars, QUIESCENT_PLAYBACK_FACTOR); + } } @Override @@ -136,15 +141,21 @@ public class KeyguardTransportControlView extends FrameLayout { } }; - private final Runnable mUpdateSeekBars = new Runnable() { + private class UpdateSeekBarRunnable implements Runnable { public void run() { - if (updateSeekBars()) { + boolean seekAble = updateOnce(); + if (seekAble) { removeCallbacks(this); postDelayed(this, 1000); } } + public boolean updateOnce() { + return updateSeekBars(); + } }; + private final UpdateSeekBarRunnable mUpdateSeekBars = new UpdateSeekBarRunnable(); + private final Runnable mResetToMetadata = new Runnable() { public void run() { resetToMetadata(); @@ -163,6 +174,7 @@ public class KeyguardTransportControlView extends FrameLayout { } if (keyCode != -1) { sendMediaButtonClick(keyCode); + delayResetToMetadata(); // if the scrub bar is showing, keep showing it. } } }; @@ -177,25 +189,67 @@ public class KeyguardTransportControlView extends FrameLayout { } }; + // This class is here to throttle scrub position updates to the music client + class FutureSeekRunnable implements Runnable { + private int mProgress; + private boolean mPending; + + public void run() { + scrubTo(mProgress); + mPending = false; + } + + void setProgress(int progress) { + mProgress = progress; + if (!mPending) { + mPending = true; + postDelayed(this, 30); + } + } + }; + + // This is here because RemoteControlClient's method isn't visible :/ + private final static boolean playbackPositionShouldMove(int playstate) { + switch(playstate) { + case RemoteControlClient.PLAYSTATE_STOPPED: + case RemoteControlClient.PLAYSTATE_PAUSED: + case RemoteControlClient.PLAYSTATE_BUFFERING: + case RemoteControlClient.PLAYSTATE_ERROR: + case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS: + case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS: + return false; + case RemoteControlClient.PLAYSTATE_PLAYING: + case RemoteControlClient.PLAYSTATE_FAST_FORWARDING: + case RemoteControlClient.PLAYSTATE_REWINDING: + default: + return true; + } + } + + private final FutureSeekRunnable mFutureSeekRunnable = new FutureSeekRunnable(); + private final SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (fromUser) { - scrubTo(progress); + mFutureSeekRunnable.setProgress(progress); delayResetToMetadata(); + mTempDate.setTime(progress); + mTransientSeekTimeElapsed.setText(mFormat.format(mTempDate)); + } else { + updateSeekDisplay(); } - updateSeekDisplay(); } @Override public void onStartTrackingTouch(SeekBar seekBar) { - mUserSeeking = true; + delayResetToMetadata(); + removeCallbacks(mUpdateSeekBars); // don't update during user interaction } @Override public void onStopTrackingTouch(SeekBar seekBar) { - mUserSeeking = false; } }; @@ -247,17 +301,11 @@ public class KeyguardTransportControlView extends FrameLayout { if (enabled == mSeekEnabled) return; mSeekEnabled = enabled; - if (mTransientSeek.getVisibility() == VISIBLE) { + if (mTransientSeek.getVisibility() == VISIBLE && !enabled) { mTransientSeek.setVisibility(INVISIBLE); mMetadataContainer.setVisibility(VISIBLE); - mUserSeeking = false; cancelResetToMetadata(); } - if (enabled) { - mUpdateSeekBars.run(); - } else { - removeCallbacks(mUpdateSeekBars); - } } public void setTransportControlCallback(KeyguardHostView.TransportControlCallback @@ -294,6 +342,8 @@ public class KeyguardTransportControlView extends FrameLayout { } final boolean screenOn = KeyguardUpdateMonitor.getInstance(mContext).isScreenOn(); setEnableMarquee(screenOn); + // Allow long-press anywhere else in this view to show the seek bar + setOnLongClickListener(mTransportShowSeekBarListener); } @Override @@ -326,7 +376,6 @@ public class KeyguardTransportControlView extends FrameLayout { mAudioManager.unregisterRemoteController(mRemoteController); KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateMonitor); mMetadata.clear(); - mUserSeeking = false; removeCallbacks(mUpdateSeekBars); } @@ -484,18 +533,12 @@ public class KeyguardTransportControlView extends FrameLayout { void updateSeekDisplay() { if (mMetadata != null && mRemoteController != null && mFormat != null) { - if (mTimeElapsed == null) { - mTimeElapsed = new Date(); - } - if (mTrackDuration == null) { - mTrackDuration = new Date(); - } - mTimeElapsed.setTime(mRemoteController.getEstimatedMediaPosition()); - mTrackDuration.setTime(mMetadata.duration); - mTransientSeekTimeElapsed.setText(mFormat.format(mTimeElapsed)); - mTransientSeekTimeTotal.setText(mFormat.format(mTrackDuration)); + mTempDate.setTime(mRemoteController.getEstimatedMediaPosition()); + mTransientSeekTimeElapsed.setText(mFormat.format(mTempDate)); + mTempDate.setTime(mMetadata.duration); + mTransientSeekTimeTotal.setText(mFormat.format(mTempDate)); - if (DEBUG) Log.d(TAG, "updateSeekDisplay timeElapsed=" + mTimeElapsed + + if (DEBUG) Log.d(TAG, "updateSeekDisplay timeElapsed=" + mTempDate + " duration=" + mMetadata.duration); } } @@ -508,10 +551,16 @@ public class KeyguardTransportControlView extends FrameLayout { mTransientSeek.setVisibility(INVISIBLE); mMetadataContainer.setVisibility(VISIBLE); cancelResetToMetadata(); + removeCallbacks(mUpdateSeekBars); // don't update if scrubber isn't visible } else { mTransientSeek.setVisibility(VISIBLE); mMetadataContainer.setVisibility(INVISIBLE); delayResetToMetadata(); + if (playbackPositionShouldMove(mCurrentPlayState)) { + mUpdateSeekBars.run(); + } else { + mUpdateSeekBars.updateOnce(); + } } mTransportControlCallback.userActivity(); return true; @@ -573,9 +622,6 @@ public class KeyguardTransportControlView extends FrameLayout { case RemoteControlClient.PLAYSTATE_PLAYING: imageResId = R.drawable.ic_media_pause; imageDescId = R.string.keyguard_transport_pause_description; - if (mSeekEnabled) { - mUpdateSeekBars.run(); - } break; case RemoteControlClient.PLAYSTATE_BUFFERING: @@ -590,10 +636,9 @@ public class KeyguardTransportControlView extends FrameLayout { break; } - if (state != RemoteControlClient.PLAYSTATE_PLAYING) { - removeCallbacks(mUpdateSeekBars); - updateSeekBars(); - } + boolean clientSupportsSeek = mMetadata != null && mMetadata.duration > 0; + setSeekBarsEnabled(clientSupportsSeek); + mBtnPlay.setImageResource(imageResId); mBtnPlay.setContentDescription(getResources().getString(imageDescId)); mCurrentPlayState = state; @@ -601,11 +646,9 @@ public class KeyguardTransportControlView extends FrameLayout { boolean updateSeekBars() { final int position = (int) mRemoteController.getEstimatedMediaPosition(); + if (DEBUG) Log.v(TAG, "Estimated time:" + position); if (position >= 0) { - if (DEBUG) Log.v(TAG, "Seek to " + position); - if (!mUserSeeking) { - mTransientSeekBar.setProgress(position); - } + mTransientSeekBar.setProgress(position); return true; } Log.w(TAG, "Updating seek bars; received invalid estimated media position (" + @@ -671,34 +714,4 @@ public class KeyguardTransportControlView extends FrameLayout { public boolean providesClock() { return false; } - - private boolean wasPlayingRecently(int state, long stateChangeTimeMs) { - switch (state) { - case RemoteControlClient.PLAYSTATE_PLAYING: - case RemoteControlClient.PLAYSTATE_FAST_FORWARDING: - case RemoteControlClient.PLAYSTATE_REWINDING: - case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS: - case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS: - case RemoteControlClient.PLAYSTATE_BUFFERING: - // actively playing or about to play - return true; - case RemoteControlClient.PLAYSTATE_NONE: - return false; - case RemoteControlClient.PLAYSTATE_STOPPED: - case RemoteControlClient.PLAYSTATE_PAUSED: - case RemoteControlClient.PLAYSTATE_ERROR: - // we have stopped playing, check how long ago - if (DEBUG) { - if ((SystemClock.elapsedRealtime() - stateChangeTimeMs) < DISPLAY_TIMEOUT_MS) { - Log.v(TAG, "wasPlayingRecently: time < TIMEOUT was playing recently"); - } else { - Log.v(TAG, "wasPlayingRecently: time > TIMEOUT"); - } - } - return ((SystemClock.elapsedRealtime() - stateChangeTimeMs) < DISPLAY_TIMEOUT_MS); - default: - Log.e(TAG, "Unknown playback state " + state + " in wasPlayingRecently()"); - return false; - } - } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java index fd7cae6..6aa0a4b 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java @@ -61,9 +61,11 @@ import android.widget.FrameLayout; public class KeyguardViewManager { private final static boolean DEBUG = KeyguardViewMediator.DEBUG; private static String TAG = "KeyguardViewManager"; - public static boolean USE_UPPER_CASE = true; public final static String IS_SWITCHING_USER = "is_switching_user"; + // Delay dismissing keyguard to allow animations to complete. + private static final int HIDE_KEYGUARD_DELAY = 500; + // Timeout used for keypresses static final int DIGIT_PRESS_WAKE_MILLIS = 5000; @@ -509,9 +511,10 @@ public class KeyguardViewManager { mKeyguardHost.setCustomBackground(null); updateShowWallpaper(true); mKeyguardHost.removeView(lastView); + mViewMediatorCallback.keyguardGone(); } } - }, 500); + }, HIDE_KEYGUARD_DELAY); } } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java index b92ae90..4086f84 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java @@ -200,7 +200,7 @@ public class KeyguardViewMediator { // cached value of whether we are showing (need to know this to quickly // answer whether the input should be restricted) - private boolean mShowing = false; + private boolean mShowing; // true if the keyguard is hidden by another window private boolean mHidden = false; @@ -253,6 +253,11 @@ public class KeyguardViewMediator { private final float mLockSoundVolume; /** + * For managing external displays + */ + private KeyguardDisplayManager mKeyguardDisplayManager; + + /** * Cache of avatar drawables, for use by KeyguardMultiUserAvatar. */ private static MultiUserAvatarCache sMultiUserAvatarCache = new MultiUserAvatarCache(); @@ -304,6 +309,11 @@ public class KeyguardViewMediator { * Report that the keyguard is dismissable, pending the next keyguardDone call. */ void keyguardDonePending(); + + /** + * Report when keyguard is actually gone + */ + void keyguardGone(); } KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() { @@ -457,6 +467,11 @@ public class KeyguardViewMediator { public void keyguardDonePending() { mKeyguardDonePending = true; } + + @Override + public void keyguardGone() { + mKeyguardDisplayManager.hide(); + } }; private void userActivity() { @@ -483,6 +498,8 @@ public class KeyguardViewMediator { mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION)); + mKeyguardDisplayManager = new KeyguardDisplayManager(context); + mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); mUpdateMonitor = KeyguardUpdateMonitor.getInstance(context); @@ -491,6 +508,10 @@ public class KeyguardViewMediator { ? lockPatternUtils : new LockPatternUtils(mContext); mLockPatternUtils.setCurrentUser(UserHandle.USER_OWNER); + // Assume keyguard is showing (unless it's disabled) until we know for sure... + mShowing = (mUpdateMonitor.isDeviceProvisioned() || mLockPatternUtils.isSecure()) + && !mLockPatternUtils.isLockScreenDisabled(); + WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); mKeyguardViewManager = new KeyguardViewManager(context, wm, mViewMediatorCallback, @@ -1218,6 +1239,7 @@ public class KeyguardViewMediator { mShowKeyguardWakeLock.release(); } + mKeyguardDisplayManager.show(); } /** diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java index f0413d6..169899f 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewStateManager.java @@ -154,6 +154,10 @@ public class KeyguardViewStateManager implements public void onPageSwitching(View newPage, int newPageIndex) { if (mKeyguardWidgetPager != null && mChallengeLayout instanceof SlidingChallengeLayout) { boolean isCameraPage = newPage instanceof CameraWidgetFrame; + if (isCameraPage) { + CameraWidgetFrame camera = (CameraWidgetFrame) newPage; + camera.setUseFastTransition(mKeyguardWidgetPager.isWarping()); + } SlidingChallengeLayout scl = (SlidingChallengeLayout) mChallengeLayout; scl.setChallengeInteractive(!isCameraPage); final int currentFlags = mKeyguardWidgetPager.getSystemUiVisibility(); diff --git a/packages/Keyguard/src/com/android/keyguard/PagedView.java b/packages/Keyguard/src/com/android/keyguard/PagedView.java index b9404d4..53c17a5 100644 --- a/packages/Keyguard/src/com/android/keyguard/PagedView.java +++ b/packages/Keyguard/src/com/android/keyguard/PagedView.java @@ -82,13 +82,13 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc private static final float RETURN_TO_ORIGINAL_PAGE_THRESHOLD = 0.33f; // The page is moved more than halfway, automatically move to the next page on touch up. - private static final float SIGNIFICANT_MOVE_THRESHOLD = 0.4f; + private static final float SIGNIFICANT_MOVE_THRESHOLD = 0.5f; // The following constants need to be scaled based on density. The scaled versions will be // assigned to the corresponding member variables below. - private static final int FLING_THRESHOLD_VELOCITY = 500; + private static final int FLING_THRESHOLD_VELOCITY = 1500; private static final int MIN_SNAP_VELOCITY = 1500; - private static final int MIN_FLING_VELOCITY = 250; + private static final int MIN_FLING_VELOCITY = 500; // We are disabling touch interaction of the widget region for factory ROM. private static final boolean DISABLE_TOUCH_INTERACTION = false; @@ -1938,10 +1938,12 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc if (isWarping()) { dispatchOnPageEndWarp(); + notifyPageSwitching(whichPage); resetPageWarp(); + } else { + notifyPageSwitching(whichPage); } - notifyPageSwitching(whichPage); View focusedChild = getFocusedChild(); if (focusedChild != null && whichPage != mCurrentPage && focusedChild == getPageAt(mCurrentPage)) { diff --git a/packages/PrintSpooler/res/layout/print_job_config_activity_content_error.xml b/packages/PrintSpooler/res/layout/print_job_config_activity_content_error.xml index f573d9d..d9f0a9a 100644 --- a/packages/PrintSpooler/res/layout/print_job_config_activity_content_error.xml +++ b/packages/PrintSpooler/res/layout/print_job_config_activity_content_error.xml @@ -35,7 +35,6 @@ android:layout_marginBottom="32dip" android:layout_gravity="center" style="?android:attr/buttonBarButtonStyle" - android:singleLine="true" android:ellipsize="end" android:text="@string/print_error_default_message" android:textColor="@color/important_text" diff --git a/packages/PrintSpooler/res/values-af/strings.xml b/packages/PrintSpooler/res/values-af/strings.xml index b8287ae..a10a5a0 100644 --- a/packages/PrintSpooler/res/values-af/strings.xml +++ b/packages/PrintSpooler/res/values-af/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Soekkassie vertoon"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Soekkassie weggesteek"</string> <string name="print_add_printer" msgid="1088656468360653455">"Voeg drukker by"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Kies drukker"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Vergeet drukker"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> drukker gekry"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> drukkers gekry"</item> diff --git a/packages/PrintSpooler/res/values-am/strings.xml b/packages/PrintSpooler/res/values-am/strings.xml index d73cdd9..3b94d6d 100644 --- a/packages/PrintSpooler/res/values-am/strings.xml +++ b/packages/PrintSpooler/res/values-am/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"የፍለጋ ሳጥን ይታያል"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"የፍለጋ ሳጥን ተደብቋል"</string> <string name="print_add_printer" msgid="1088656468360653455">"አታሚ አክል"</string> + <string name="print_select_printer" msgid="7388760939873368698">"አታሚ ምረጥ"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"አታሚ እርሳ"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> አታሚ ተገኝቷል"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> አታሚዎች ተገኝተዋል"</item> diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml index 14b6467..b883f93 100644 --- a/packages/PrintSpooler/res/values-ar/strings.xml +++ b/packages/PrintSpooler/res/values-ar/strings.xml @@ -23,7 +23,7 @@ <string name="label_destination" msgid="9132510997381599275">"الوجهة"</string> <string name="label_copies" msgid="3634531042822968308">"عدد النسخ"</string> <string name="label_paper_size" msgid="8681895607876809323">"حجم الورق"</string> - <string name="label_color" msgid="1108690305218188969">"اللون"</string> + <string name="label_color" msgid="1108690305218188969">"ألوان"</string> <string name="label_orientation" msgid="2853142581990496477">"الاتجاه"</string> <string name="label_pages" msgid="6300874667546617333">"الصفحات (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string> <string name="pages_range_example" msgid="8558694453556945172">"على سبيل المثال، 1—5،8،11—13"</string> @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"تم إظهار مربع البحث"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"تم إخفاء مربع البحث"</string> <string name="print_add_printer" msgid="1088656468360653455">"إضافة طابعة"</string> + <string name="print_select_printer" msgid="7388760939873368698">"حدد الطابعة"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"تجاهل الطابعة"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"تم العثور على <xliff:g id="COUNT">%1$s</xliff:g> طابعة"</item> <item quantity="other" msgid="6533817036607128241">"تم العثور على <xliff:g id="COUNT">%1$s</xliff:g> من الطابعات"</item> @@ -64,11 +66,11 @@ <string name="print_error_default_message" msgid="8568506918983980567">"تعذر إنشاء عملية الطباعة"</string> <string-array name="color_mode_labels"> <item msgid="7602948745415174937">"أبيض وأسود"</item> - <item msgid="2762241247228983754">"اللون"</item> + <item msgid="2762241247228983754">"ملونة"</item> </string-array> <string-array name="orientation_labels"> <item msgid="4061931020926489228">"عمودي"</item> - <item msgid="3199660090246166812">"أفقية"</item> + <item msgid="3199660090246166812">"أفقي"</item> </string-array> <string-array name="page_options_labels"> <item msgid="7421377442011699994">"الكل"</item> diff --git a/packages/PrintSpooler/res/values-bg/strings.xml b/packages/PrintSpooler/res/values-bg/strings.xml index 47f86c6..4009aa2 100644 --- a/packages/PrintSpooler/res/values-bg/strings.xml +++ b/packages/PrintSpooler/res/values-bg/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Полето за търсене е показано"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Полето за търсене е скрито"</string> <string name="print_add_printer" msgid="1088656468360653455">"Добавяне на принтер"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Избиране на принтер"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Забравяне на принтера"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Намерен е <xliff:g id="COUNT">%1$s</xliff:g> принтер"</item> <item quantity="other" msgid="6533817036607128241">"Намерени са <xliff:g id="COUNT">%1$s</xliff:g> принтера"</item> diff --git a/packages/PrintSpooler/res/values-ca/strings.xml b/packages/PrintSpooler/res/values-ca/strings.xml index fc60b0a..a429dd5 100644 --- a/packages/PrintSpooler/res/values-ca/strings.xml +++ b/packages/PrintSpooler/res/values-ca/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Es mostra el quadre de cerca"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"S\'ha amagat el quadre de cerca"</string> <string name="print_add_printer" msgid="1088656468360653455">"Afegeix una impressora"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Selecciona una impressora"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Oblida la impressora"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"S\'ha trobat <xliff:g id="COUNT">%1$s</xliff:g> impressora"</item> <item quantity="other" msgid="6533817036607128241">"S\'han trobat <xliff:g id="COUNT">%1$s</xliff:g> impressores"</item> diff --git a/packages/PrintSpooler/res/values-cs/strings.xml b/packages/PrintSpooler/res/values-cs/strings.xml index 3f806d6..3ddc701 100644 --- a/packages/PrintSpooler/res/values-cs/strings.xml +++ b/packages/PrintSpooler/res/values-cs/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Vyhledávací pole se zobrazuje"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Vyhledávací pole je skryto"</string> <string name="print_add_printer" msgid="1088656468360653455">"Přidat tiskárnu"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Vybrat tiskárnu"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Odstranit tiskárnu"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Počet nalezených tiskáren: <xliff:g id="COUNT">%1$s</xliff:g>"</item> <item quantity="other" msgid="6533817036607128241">"Počet nalezených tiskáren: <xliff:g id="COUNT">%1$s</xliff:g>"</item> diff --git a/packages/PrintSpooler/res/values-da/strings.xml b/packages/PrintSpooler/res/values-da/strings.xml index 60c22bb..74190b4 100644 --- a/packages/PrintSpooler/res/values-da/strings.xml +++ b/packages/PrintSpooler/res/values-da/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Søgefeltet vises"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Søgefeltet er skjult"</string> <string name="print_add_printer" msgid="1088656468360653455">"Tilføj printer"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Vælg printer"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Glem printer"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Der blev fundet <xliff:g id="COUNT">%1$s</xliff:g> printer"</item> <item quantity="other" msgid="6533817036607128241">"Der blev fundet <xliff:g id="COUNT">%1$s</xliff:g> printere"</item> diff --git a/packages/PrintSpooler/res/values-de/strings.xml b/packages/PrintSpooler/res/values-de/strings.xml index 54c936f..6b83ac3 100644 --- a/packages/PrintSpooler/res/values-de/strings.xml +++ b/packages/PrintSpooler/res/values-de/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Suchfeld angezeigt"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Suchfeld ausgeblendet"</string> <string name="print_add_printer" msgid="1088656468360653455">"Drucker hinzufügen"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Drucker auswählen"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Drucker wieder vergessen"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> Drucker gefunden"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> Drucker gefunden"</item> diff --git a/packages/PrintSpooler/res/values-el/strings.xml b/packages/PrintSpooler/res/values-el/strings.xml index 168f87b..795e730 100644 --- a/packages/PrintSpooler/res/values-el/strings.xml +++ b/packages/PrintSpooler/res/values-el/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Εμφάνιση πλαισίου αναζήτησης"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Απόκρυψη πλαισίου αναζήτησης"</string> <string name="print_add_printer" msgid="1088656468360653455">"Προσθήκη εκτυπωτή"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Επιλογή εκτυπωτή"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Διαγραφή εκτυπωτή"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Βρέθηκε <xliff:g id="COUNT">%1$s</xliff:g> εκτυπωτής"</item> <item quantity="other" msgid="6533817036607128241">"Βρέθηκαν <xliff:g id="COUNT">%1$s</xliff:g> εκτυπωτές"</item> diff --git a/packages/PrintSpooler/res/values-en-rGB/strings.xml b/packages/PrintSpooler/res/values-en-rGB/strings.xml index 98c3688..27372f8 100644 --- a/packages/PrintSpooler/res/values-en-rGB/strings.xml +++ b/packages/PrintSpooler/res/values-en-rGB/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Search box shown"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Search box hidden"</string> <string name="print_add_printer" msgid="1088656468360653455">"Add printer"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Select printer"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Forget printer"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> printer found"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> printers found"</item> diff --git a/packages/PrintSpooler/res/values-en-rIN/strings.xml b/packages/PrintSpooler/res/values-en-rIN/strings.xml index 98c3688..27372f8 100644 --- a/packages/PrintSpooler/res/values-en-rIN/strings.xml +++ b/packages/PrintSpooler/res/values-en-rIN/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Search box shown"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Search box hidden"</string> <string name="print_add_printer" msgid="1088656468360653455">"Add printer"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Select printer"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Forget printer"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> printer found"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> printers found"</item> diff --git a/packages/PrintSpooler/res/values-es-rUS/strings.xml b/packages/PrintSpooler/res/values-es-rUS/strings.xml index bfdf933..c7d12af 100644 --- a/packages/PrintSpooler/res/values-es-rUS/strings.xml +++ b/packages/PrintSpooler/res/values-es-rUS/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Cuadro de búsqueda visible"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Cuadro de búsqueda oculto"</string> <string name="print_add_printer" msgid="1088656468360653455">"Agregar impresora"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Seleccionar impresora"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"No recordar impresora"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Se encontró <xliff:g id="COUNT">%1$s</xliff:g> impresora."</item> <item quantity="other" msgid="6533817036607128241">"Se encontraron <xliff:g id="COUNT">%1$s</xliff:g> impresoras."</item> diff --git a/packages/PrintSpooler/res/values-es/strings.xml b/packages/PrintSpooler/res/values-es/strings.xml index 28df5f0..0225cad 100644 --- a/packages/PrintSpooler/res/values-es/strings.xml +++ b/packages/PrintSpooler/res/values-es/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Cuadro de búsqueda visible"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Cuadro de búsqueda oculto"</string> <string name="print_add_printer" msgid="1088656468360653455">"Añadir impresora"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Seleccionar impresora"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Borrar impresora"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Se ha encontrado <xliff:g id="COUNT">%1$s</xliff:g> impresora"</item> <item quantity="other" msgid="6533817036607128241">"Se han encontrado <xliff:g id="COUNT">%1$s</xliff:g> impresoras"</item> diff --git a/packages/PrintSpooler/res/values-et-rEE/strings.xml b/packages/PrintSpooler/res/values-et-rEE/strings.xml index 1114f9f..2b3b352 100644 --- a/packages/PrintSpooler/res/values-et-rEE/strings.xml +++ b/packages/PrintSpooler/res/values-et-rEE/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Otsingukast on kuvatud"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Otsingukast on peidetud"</string> <string name="print_add_printer" msgid="1088656468360653455">"Lisa printer"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Printeri valimine"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Printeri unustamine"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Leiti <xliff:g id="COUNT">%1$s</xliff:g> printer"</item> <item quantity="other" msgid="6533817036607128241">"Leiti <xliff:g id="COUNT">%1$s</xliff:g> printerit"</item> diff --git a/packages/PrintSpooler/res/values-fa/strings.xml b/packages/PrintSpooler/res/values-fa/strings.xml index 950ef92..49bae32 100644 --- a/packages/PrintSpooler/res/values-fa/strings.xml +++ b/packages/PrintSpooler/res/values-fa/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"کادر جستجو نمایان شد"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"کادر جستجو پنهان شد"</string> <string name="print_add_printer" msgid="1088656468360653455">"افزودن چاپگر"</string> + <string name="print_select_printer" msgid="7388760939873368698">"انتخاب چاپگر"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"فراموش کردن چاپگر"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> چاپگر یافت شد"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> چاپگر یافت شد"</item> diff --git a/packages/PrintSpooler/res/values-fi/strings.xml b/packages/PrintSpooler/res/values-fi/strings.xml index 239afcf..8658e04 100644 --- a/packages/PrintSpooler/res/values-fi/strings.xml +++ b/packages/PrintSpooler/res/values-fi/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Hakukenttä näkyvissä"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Hakukenttä piilotettu"</string> <string name="print_add_printer" msgid="1088656468360653455">"Lisää tulostin"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Valitse tulostin"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Unohda tulostin"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Löytyi <xliff:g id="COUNT">%1$s</xliff:g> tulostin"</item> <item quantity="other" msgid="6533817036607128241">"Löytyi <xliff:g id="COUNT">%1$s</xliff:g> tulostinta"</item> diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml index 3880745..9a3352c 100644 --- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml +++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Champ de recherche affiché"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Champ de recherche masqué"</string> <string name="print_add_printer" msgid="1088656468360653455">"Ajouter une imprimante"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Sélectionner une imprimante"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Supprimer l\'imprimante"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> imprimante trouvée"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> imprimantes trouvées"</item> diff --git a/packages/PrintSpooler/res/values-fr/strings.xml b/packages/PrintSpooler/res/values-fr/strings.xml index 961d344..cfb557e 100644 --- a/packages/PrintSpooler/res/values-fr/strings.xml +++ b/packages/PrintSpooler/res/values-fr/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Champ de recherche affiché."</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Champ de recherche masqué."</string> <string name="print_add_printer" msgid="1088656468360653455">"Ajouter une imprimante"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Sélectionner une imprimante"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Supprimer l\'imprimante"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> imprimante trouvée."</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> imprimantes trouvées."</item> diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml index 4d1ddd8..60406b7 100644 --- a/packages/PrintSpooler/res/values-hi/strings.xml +++ b/packages/PrintSpooler/res/values-hi/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"खोज बॉक्स प्रदर्शित है"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"खोज बॉक्स छिपा हुआ है"</string> <string name="print_add_printer" msgid="1088656468360653455">"प्रिंटर जोड़ें"</string> + <string name="print_select_printer" msgid="7388760939873368698">"प्रिंटर चुनें"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"प्रिंटर को भूल जाएं"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> प्रिंटर मिला"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> प्रिंटर मिले"</item> diff --git a/packages/PrintSpooler/res/values-hr/strings.xml b/packages/PrintSpooler/res/values-hr/strings.xml index 50b56ff..7182cf6 100644 --- a/packages/PrintSpooler/res/values-hr/strings.xml +++ b/packages/PrintSpooler/res/values-hr/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Okvir za pretraživanje prikazan je"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Okvir za pretraživanje skriven je"</string> <string name="print_add_printer" msgid="1088656468360653455">"Dodaj pisač"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Odaberite pisač"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Zaboravite pisač"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Pronađen je <xliff:g id="COUNT">%1$s</xliff:g> pisač"</item> <item quantity="other" msgid="6533817036607128241">"Pronađen je sljedeći broj pisača: <xliff:g id="COUNT">%1$s</xliff:g>"</item> diff --git a/packages/PrintSpooler/res/values-hu/strings.xml b/packages/PrintSpooler/res/values-hu/strings.xml index 79912fc..6a0741b 100644 --- a/packages/PrintSpooler/res/values-hu/strings.xml +++ b/packages/PrintSpooler/res/values-hu/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Keresőmező megjelenítve"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Keresőmező elrejtve"</string> <string name="print_add_printer" msgid="1088656468360653455">"Nyomtató hozzáadása"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Nyomtató kiválasztása"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Nyomtató elfelejtése"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> nyomtató észlelve"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> nyomtató észlelve"</item> diff --git a/packages/PrintSpooler/res/values-hy-rAM/strings.xml b/packages/PrintSpooler/res/values-hy-rAM/strings.xml index 7d95f7b..1423b82 100644 --- a/packages/PrintSpooler/res/values-hy-rAM/strings.xml +++ b/packages/PrintSpooler/res/values-hy-rAM/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Որոնման վանդակը ցուցադրված է"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Որոնման վանդակը թաքցվել է"</string> <string name="print_add_printer" msgid="1088656468360653455">"Ավելացնել տպիչ"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Ընտրել տպիչ"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Մոռանալ տպիչը"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> տպիչ է գտնվել"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> տպիչ է գտնվել"</item> diff --git a/packages/PrintSpooler/res/values-in/strings.xml b/packages/PrintSpooler/res/values-in/strings.xml index 1206676..2b80d07 100644 --- a/packages/PrintSpooler/res/values-in/strings.xml +++ b/packages/PrintSpooler/res/values-in/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Kotak telusur ditampilkan"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Kotak telusur disembunyikan"</string> <string name="print_add_printer" msgid="1088656468360653455">"Tambahkan printer"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Pilih printer"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Lupakan printer"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> printer ditemukan"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> printer ditemukan"</item> diff --git a/packages/PrintSpooler/res/values-it/strings.xml b/packages/PrintSpooler/res/values-it/strings.xml index 4223188..96c3b48 100644 --- a/packages/PrintSpooler/res/values-it/strings.xml +++ b/packages/PrintSpooler/res/values-it/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Casella di ricerca visualizzata"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Casella di ricerca nascosta"</string> <string name="print_add_printer" msgid="1088656468360653455">"Aggiungi stampante"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Seleziona stampante"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Elimina stampante"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> stampante trovata"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> stampanti trovate"</item> diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml index 2a9e0df..3e0e732 100644 --- a/packages/PrintSpooler/res/values-iw/strings.xml +++ b/packages/PrintSpooler/res/values-iw/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"תיבת החיפוש מוצגת"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"תיבת החיפוש מוסתרת"</string> <string name="print_add_printer" msgid="1088656468360653455">"הוסף מדפסת"</string> + <string name="print_select_printer" msgid="7388760939873368698">"בחר מדפסת"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"שכח את המדפסת"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"נמצאה מדפסת <xliff:g id="COUNT">%1$s</xliff:g>"</item> <item quantity="other" msgid="6533817036607128241">"נמצאו <xliff:g id="COUNT">%1$s</xliff:g> מדפסות"</item> diff --git a/packages/PrintSpooler/res/values-ja/arrays.xml b/packages/PrintSpooler/res/values-ja/arrays.xml index 57088c8..460bdb2 100644 --- a/packages/PrintSpooler/res/values-ja/arrays.xml +++ b/packages/PrintSpooler/res/values-ja/arrays.xml @@ -20,13 +20,13 @@ <item>JIS_B9</item> <item>JIS_B8</item> <item>JIS_B7</item> - <item>JIS_b6</item> - <item>JIS_b5</item> - <item>JIS_b4</item> - <item>JIS_b3</item> - <item>JIS_b2</item> - <item>JIS_b1</item> - <item>JIS_b0</item> + <item>JIS_B6</item> + <item>JIS_B5</item> + <item>JIS_B4</item> + <item>JIS_B3</item> + <item>JIS_B2</item> + <item>JIS_B1</item> + <item>JIS_B0</item> <item>JIS_EXEC</item> <item>JPN_CHOU4</item> <item>JPN_CHOU3</item> diff --git a/packages/PrintSpooler/res/values-ja/strings.xml b/packages/PrintSpooler/res/values-ja/strings.xml index e6ae97a..94e8441 100644 --- a/packages/PrintSpooler/res/values-ja/strings.xml +++ b/packages/PrintSpooler/res/values-ja/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"検索ボックスは表示されています"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"検索ボックスは表示されていません"</string> <string name="print_add_printer" msgid="1088656468360653455">"プリンタを追加"</string> + <string name="print_select_printer" msgid="7388760939873368698">"プリンタを選択"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"プリンタを切断"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g>台のプリンタが見つかりました"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g>台のプリンタが見つかりました"</item> diff --git a/packages/PrintSpooler/res/values-ka-rGE/strings.xml b/packages/PrintSpooler/res/values-ka-rGE/strings.xml index 3fc1f3a..d36b7c9 100644 --- a/packages/PrintSpooler/res/values-ka-rGE/strings.xml +++ b/packages/PrintSpooler/res/values-ka-rGE/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"საძიებო ველი ნაჩვენებია"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"საძიებო ველი დამალულია"</string> <string name="print_add_printer" msgid="1088656468360653455">"პრინტერის დამატება"</string> + <string name="print_select_printer" msgid="7388760939873368698">"პრინტერის არჩევა"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"პრინტერის დავიწყება"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"ნაპოვნია <xliff:g id="COUNT">%1$s</xliff:g> პრინტერი"</item> <item quantity="other" msgid="6533817036607128241">"ნაპოვნია <xliff:g id="COUNT">%1$s</xliff:g> პრინტერი"</item> diff --git a/packages/PrintSpooler/res/values-km-rKH/strings.xml b/packages/PrintSpooler/res/values-km-rKH/strings.xml index 8ed8527..c89f9bf 100644 --- a/packages/PrintSpooler/res/values-km-rKH/strings.xml +++ b/packages/PrintSpooler/res/values-km-rKH/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"បានបង្ហាញប្រអប់ស្វែងរក"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"បានលាក់ប្រអប់ស្វែងរក"</string> <string name="print_add_printer" msgid="1088656468360653455">"បន្ថែមម៉ាស៊ីនបោះពុម្ព"</string> + <string name="print_select_printer" msgid="7388760939873368698">"ជ្រើសម៉ាស៊ីនបោះពុម្ព"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"ភ្លេចម៉ាស៊ីនបោះពុម្ព"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"រកឃើញម៉ាស៊ីនបោះពុម្ព <xliff:g id="COUNT">%1$s</xliff:g>"</item> <item quantity="other" msgid="6533817036607128241">"រកឃើញម៉ាស៊ីនបោះពុម្ព <xliff:g id="COUNT">%1$s</xliff:g>"</item> diff --git a/packages/PrintSpooler/res/values-ko/strings.xml b/packages/PrintSpooler/res/values-ko/strings.xml index 83155fd..3b2fef7 100644 --- a/packages/PrintSpooler/res/values-ko/strings.xml +++ b/packages/PrintSpooler/res/values-ko/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"검색창 표시됨"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"검색창 숨겨짐"</string> <string name="print_add_printer" msgid="1088656468360653455">"프린터 추가"</string> + <string name="print_select_printer" msgid="7388760939873368698">"프린터 선택"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"프린터 삭제"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"프린터 <xliff:g id="COUNT">%1$s</xliff:g>대 검색됨"</item> <item quantity="other" msgid="6533817036607128241">"프린터 <xliff:g id="COUNT">%1$s</xliff:g>대 검색됨"</item> diff --git a/packages/PrintSpooler/res/values-lo-rLA/strings.xml b/packages/PrintSpooler/res/values-lo-rLA/strings.xml index 45bb9bc..f954606 100644 --- a/packages/PrintSpooler/res/values-lo-rLA/strings.xml +++ b/packages/PrintSpooler/res/values-lo-rLA/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"ກ່ອງຊອກຫາຖືກສະແດງ"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"ກ່ອງຊອກຫາຖືກເຊື່ອງ"</string> <string name="print_add_printer" msgid="1088656468360653455">"ເພີ່ມເຄື່ອງພິມ"</string> + <string name="print_select_printer" msgid="7388760939873368698">"ເລືອກເຄື່ອງພິມ"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"ລືມເຄື່ອງພິມ"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"ພົບ <xliff:g id="COUNT">%1$s</xliff:g> ເຄື່ອງພິມ"</item> <item quantity="other" msgid="6533817036607128241">"ພົບ <xliff:g id="COUNT">%1$s</xliff:g> ເຄື່ອງພິມ"</item> diff --git a/packages/PrintSpooler/res/values-lt/strings.xml b/packages/PrintSpooler/res/values-lt/strings.xml index 1560dce..0c4e386 100644 --- a/packages/PrintSpooler/res/values-lt/strings.xml +++ b/packages/PrintSpooler/res/values-lt/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Paieškos laukelis rodomas"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Paieškos laukelis paslėptas"</string> <string name="print_add_printer" msgid="1088656468360653455">"Pridėti spausdintuvą"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Pasirinkti spausdintuvą"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Pamiršti spausdintuvą"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Rasta spausdintuvų: <xliff:g id="COUNT">%1$s</xliff:g>"</item> <item quantity="other" msgid="6533817036607128241">"Rasta spausdintuvų: <xliff:g id="COUNT">%1$s</xliff:g>"</item> diff --git a/packages/PrintSpooler/res/values-lv/strings.xml b/packages/PrintSpooler/res/values-lv/strings.xml index 3a6049c..3fffdfe 100644 --- a/packages/PrintSpooler/res/values-lv/strings.xml +++ b/packages/PrintSpooler/res/values-lv/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Meklēšanas lodziņš ir redzams."</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Meklēšanas lodziņš ir paslēpts."</string> <string name="print_add_printer" msgid="1088656468360653455">"Pievienot printeri"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Atlasīt printeri"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Neatcerēties printeri"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Atrasts <xliff:g id="COUNT">%1$s</xliff:g> printeris"</item> <item quantity="other" msgid="6533817036607128241">"Atrasti <xliff:g id="COUNT">%1$s</xliff:g> printeri"</item> diff --git a/packages/PrintSpooler/res/values-mn-rMN/strings.xml b/packages/PrintSpooler/res/values-mn-rMN/strings.xml index 8062eb1..e429387 100644 --- a/packages/PrintSpooler/res/values-mn-rMN/strings.xml +++ b/packages/PrintSpooler/res/values-mn-rMN/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Хайлтын нүдийг гаргах"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Хайлтын нүдийг далдлах"</string> <string name="print_add_printer" msgid="1088656468360653455">"Принтер нэмэх"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Принтер сонгох"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Принтерийг мартах"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> принтер олдсон"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> принтер олдсон"</item> diff --git a/packages/PrintSpooler/res/values-ms-rMY/strings.xml b/packages/PrintSpooler/res/values-ms-rMY/strings.xml index d113749..cca5d2c 100644 --- a/packages/PrintSpooler/res/values-ms-rMY/strings.xml +++ b/packages/PrintSpooler/res/values-ms-rMY/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Kotak carian ditunjukkan"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Kotak carian tersembunyi"</string> <string name="print_add_printer" msgid="1088656468360653455">"Tambah pencetak"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Pilih pencetak"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Lupakan pencetak"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> pencetak ditemui"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> pencetak ditemui"</item> diff --git a/packages/PrintSpooler/res/values-nb/strings.xml b/packages/PrintSpooler/res/values-nb/strings.xml index abed60d..f6a60c6 100644 --- a/packages/PrintSpooler/res/values-nb/strings.xml +++ b/packages/PrintSpooler/res/values-nb/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Søkefeltet vises"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Søkefeltet er skjult"</string> <string name="print_add_printer" msgid="1088656468360653455">"Legg til skriver"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Velg skriver"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Glem skriveren"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> skriver ble funnet"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> skrivere ble funnet"</item> diff --git a/packages/PrintSpooler/res/values-nl/strings.xml b/packages/PrintSpooler/res/values-nl/strings.xml index 3289d12..dc12508 100644 --- a/packages/PrintSpooler/res/values-nl/strings.xml +++ b/packages/PrintSpooler/res/values-nl/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Zoekvak weergegeven"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Zoekvak verborgen"</string> <string name="print_add_printer" msgid="1088656468360653455">"Printer toevoegen"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Printer selecteren"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Printer vergeten"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> printer gevonden"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> printers gevonden"</item> diff --git a/packages/PrintSpooler/res/values-pl/strings.xml b/packages/PrintSpooler/res/values-pl/strings.xml index 10cb2e7..81acc76 100644 --- a/packages/PrintSpooler/res/values-pl/strings.xml +++ b/packages/PrintSpooler/res/values-pl/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Pole wyszukiwania jest widoczne"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Pole wyszukiwania jest ukryte"</string> <string name="print_add_printer" msgid="1088656468360653455">"Dodaj drukarkę"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Wybierz drukarkę"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Nie zapamiętuj drukarki"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Znaleziono <xliff:g id="COUNT">%1$s</xliff:g> drukarkę"</item> <item quantity="other" msgid="6533817036607128241">"Znalezione drukarki: <xliff:g id="COUNT">%1$s</xliff:g>"</item> diff --git a/packages/PrintSpooler/res/values-pt-rPT/strings.xml b/packages/PrintSpooler/res/values-pt-rPT/strings.xml index 630fe03..6bfc395 100644 --- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml +++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Caixa de pesquisa apresentada"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Caixa de pesquisa ocultada"</string> <string name="print_add_printer" msgid="1088656468360653455">"Adicionar impressora"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Selecionar impressora"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Esquecer impressora"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> impressora encontrada"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> impressoras encontradas"</item> diff --git a/packages/PrintSpooler/res/values-pt/strings.xml b/packages/PrintSpooler/res/values-pt/strings.xml index 6e5eab1..82c157d 100644 --- a/packages/PrintSpooler/res/values-pt/strings.xml +++ b/packages/PrintSpooler/res/values-pt/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Caixa de pesquisa exibida"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Caixa de pesquisa oculta"</string> <string name="print_add_printer" msgid="1088656468360653455">"Adicionar impressora"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Selecionar impressora"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Esquecer impressora"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> impressora encontrada"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> impressoras encontradas"</item> diff --git a/packages/PrintSpooler/res/values-ro/strings.xml b/packages/PrintSpooler/res/values-ro/strings.xml index c4d9f8e..79c3bdc 100644 --- a/packages/PrintSpooler/res/values-ro/strings.xml +++ b/packages/PrintSpooler/res/values-ro/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Caseta de căutare este afișată"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Caseta de căutare este ascunsă"</string> <string name="print_add_printer" msgid="1088656468360653455">"Adăugați o imprimantă"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Selectați imprimanta"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Omiteți imprimanta"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> imprimantă găsită"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> (de) imprimante găsite"</item> diff --git a/packages/PrintSpooler/res/values-ru/strings.xml b/packages/PrintSpooler/res/values-ru/strings.xml index b1335a0..a27f3c8 100644 --- a/packages/PrintSpooler/res/values-ru/strings.xml +++ b/packages/PrintSpooler/res/values-ru/strings.xml @@ -22,8 +22,8 @@ <string name="save_button" msgid="1921310454071758999">"Сохранить"</string> <string name="label_destination" msgid="9132510997381599275">"Принтер"</string> <string name="label_copies" msgid="3634531042822968308">"Копии"</string> - <string name="label_paper_size" msgid="8681895607876809323">"Размер бумаги"</string> - <string name="label_color" msgid="1108690305218188969">"Цветной"</string> + <string name="label_paper_size" msgid="8681895607876809323">"Формат"</string> + <string name="label_color" msgid="1108690305218188969">"Печать"</string> <string name="label_orientation" msgid="2853142581990496477">"Ориентация"</string> <string name="label_pages" msgid="6300874667546617333">"СТРАНИЦЫ (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string> <string name="pages_range_example" msgid="8558694453556945172">"напр., 1–5, 8, 11–13"</string> @@ -32,7 +32,7 @@ <string name="printing_app_crashed" msgid="854477616686566398">"Сбой приложения печати"</string> <string name="page_count_unknown" msgid="6058852665954511124">"Количество страниц"</string> <string name="generating_print_job" msgid="3119608742651698916">"Создание задания печати…"</string> - <string name="save_as_pdf" msgid="5718454119847596853">"Сохранить как PDF-файл"</string> + <string name="save_as_pdf" msgid="5718454119847596853">"Сохранить как PDF"</string> <string name="all_printers" msgid="5018829726861876202">"Все принтеры"</string> <string name="print_dialog" msgid="32628687461331979">"Диалоговое окно печати"</string> <string name="search" msgid="5421724265322228497">"Поиск"</string> @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Окно поиска показано"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Окно поиска скрыто"</string> <string name="print_add_printer" msgid="1088656468360653455">"Добавить принтер"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Выбрать принтер"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Удалить принтер"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Найден <xliff:g id="COUNT">%1$s</xliff:g> принтер"</item> <item quantity="other" msgid="6533817036607128241">"Найдено принтеров: <xliff:g id="COUNT">%1$s</xliff:g>"</item> @@ -63,12 +65,12 @@ <string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – недоступен"</string> <string name="print_error_default_message" msgid="8568506918983980567">"Не удалось отправить документ на печать."</string> <string-array name="color_mode_labels"> - <item msgid="7602948745415174937">"Черно-белое"</item> - <item msgid="2762241247228983754">"Цветное"</item> + <item msgid="7602948745415174937">"Черно-белая"</item> + <item msgid="2762241247228983754">"Цветная"</item> </string-array> <string-array name="orientation_labels"> - <item msgid="4061931020926489228">"Книжная"</item> - <item msgid="3199660090246166812">"Альбомная"</item> + <item msgid="4061931020926489228">"Книга"</item> + <item msgid="3199660090246166812">"Альбом"</item> </string-array> <string-array name="page_options_labels"> <item msgid="7421377442011699994">"Все"</item> diff --git a/packages/PrintSpooler/res/values-sk/strings.xml b/packages/PrintSpooler/res/values-sk/strings.xml index 922a759..39a022d 100644 --- a/packages/PrintSpooler/res/values-sk/strings.xml +++ b/packages/PrintSpooler/res/values-sk/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Vyhľadávacie pole sa zobrazuje"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Vyhľadávacie pole je skryté"</string> <string name="print_add_printer" msgid="1088656468360653455">"Pridať tlačiareň"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Vybrať tlačiareň"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Odstrániť tlačiareň"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Našla sa <xliff:g id="COUNT">%1$s</xliff:g> tlačiareň"</item> <item quantity="other" msgid="6533817036607128241">"Počet nájdených tlačiarní: <xliff:g id="COUNT">%1$s</xliff:g>"</item> diff --git a/packages/PrintSpooler/res/values-sl/strings.xml b/packages/PrintSpooler/res/values-sl/strings.xml index abd07c6..5d4fe94 100644 --- a/packages/PrintSpooler/res/values-sl/strings.xml +++ b/packages/PrintSpooler/res/values-sl/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Iskalno polje je prikazano"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Iskalno polje je skrito"</string> <string name="print_add_printer" msgid="1088656468360653455">"Dodajanje tiskalnika"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Izbira tiskalnika"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Odstranitev tiskalnika"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Najden <xliff:g id="COUNT">%1$s</xliff:g> tiskalnik"</item> <item quantity="other" msgid="6533817036607128241">"Število najdenih tiskalnikov: <xliff:g id="COUNT">%1$s</xliff:g>"</item> diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml index 24f4797..cbab1a6 100644 --- a/packages/PrintSpooler/res/values-sr/strings.xml +++ b/packages/PrintSpooler/res/values-sr/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Оквир за претрагу је приказан"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Оквир за претрагу је сакривен"</string> <string name="print_add_printer" msgid="1088656468360653455">"Додај штампач"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Изабери штампач"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Заборави штампач"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Пронађен је <xliff:g id="COUNT">%1$s</xliff:g> штампач"</item> <item quantity="other" msgid="6533817036607128241">"Пронађено је <xliff:g id="COUNT">%1$s</xliff:g> штампача"</item> diff --git a/packages/PrintSpooler/res/values-sv/strings.xml b/packages/PrintSpooler/res/values-sv/strings.xml index 2d80858..2286fce 100644 --- a/packages/PrintSpooler/res/values-sv/strings.xml +++ b/packages/PrintSpooler/res/values-sv/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Sökrutan visas"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Sökrutan är dold"</string> <string name="print_add_printer" msgid="1088656468360653455">"Lägg till skrivare"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Välj en skrivare"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Ta bort en skrivare"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> skrivare hittades"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> skrivare hittades"</item> diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml index 3873d37..55c8687 100644 --- a/packages/PrintSpooler/res/values-sw/strings.xml +++ b/packages/PrintSpooler/res/values-sw/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Kisanduku cha kutafutia kimeonyeshwa"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Kisanduku cha kutafutia kimefichwa"</string> <string name="print_add_printer" msgid="1088656468360653455">"Ongeza printa"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Chagua printa"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Sahau printa"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Printa <xliff:g id="COUNT">%1$s</xliff:g> imepatikana"</item> <item quantity="other" msgid="6533817036607128241">"Printa <xliff:g id="COUNT">%1$s</xliff:g> zimepatikana"</item> diff --git a/packages/PrintSpooler/res/values-th/strings.xml b/packages/PrintSpooler/res/values-th/strings.xml index 7d6523e..aa01d6f 100644 --- a/packages/PrintSpooler/res/values-th/strings.xml +++ b/packages/PrintSpooler/res/values-th/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"แสดงช่องค้นหาอยู่"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"ซ่อนช่องค้นหาอยู่"</string> <string name="print_add_printer" msgid="1088656468360653455">"เพิ่มเครื่องพิมพ์"</string> + <string name="print_select_printer" msgid="7388760939873368698">"เลือกเครื่องพิมพ์"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"ไม่ต้องจำเครื่องพิมพ์"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"พบเครื่องพิมพ์ <xliff:g id="COUNT">%1$s</xliff:g> เครื่อง"</item> <item quantity="other" msgid="6533817036607128241">"พบเครื่องพิมพ์ <xliff:g id="COUNT">%1$s</xliff:g> เครื่อง"</item> diff --git a/packages/PrintSpooler/res/values-tl/strings.xml b/packages/PrintSpooler/res/values-tl/strings.xml index 238c6bc..a72c937 100644 --- a/packages/PrintSpooler/res/values-tl/strings.xml +++ b/packages/PrintSpooler/res/values-tl/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Ipinapakita ang box para sa paghahanap"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Nakatago ang box para sa paghahanap"</string> <string name="print_add_printer" msgid="1088656468360653455">"Magdagdag ng printer"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Piliin ang printer"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Kalimutan ang printer"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> printer ang nakita"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> (na) printer ang nakita"</item> diff --git a/packages/PrintSpooler/res/values-tr/strings.xml b/packages/PrintSpooler/res/values-tr/strings.xml index f851f20..c6e302d 100644 --- a/packages/PrintSpooler/res/values-tr/strings.xml +++ b/packages/PrintSpooler/res/values-tr/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Arama kutusu gösteriliyor"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Arama kutusu gizli"</string> <string name="print_add_printer" msgid="1088656468360653455">"Yazıcı ekle"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Yazıcı seç"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Yazıcıyı unut"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> yazıcı bulundu"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> yazıcı bulundu"</item> diff --git a/packages/PrintSpooler/res/values-uk/strings.xml b/packages/PrintSpooler/res/values-uk/strings.xml index 8a340f1..4f526d0 100644 --- a/packages/PrintSpooler/res/values-uk/strings.xml +++ b/packages/PrintSpooler/res/values-uk/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Вікно пошуку показано"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Вікно пошуку сховано"</string> <string name="print_add_printer" msgid="1088656468360653455">"Додати принтер"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Вибрати принтер"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Ігнорувати принтер"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Знайдено принтерів: <xliff:g id="COUNT">%1$s</xliff:g>"</item> <item quantity="other" msgid="6533817036607128241">"Знайдено принтерів: <xliff:g id="COUNT">%1$s</xliff:g>"</item> diff --git a/packages/PrintSpooler/res/values-vi/strings.xml b/packages/PrintSpooler/res/values-vi/strings.xml index 7d086ad..d21172c 100644 --- a/packages/PrintSpooler/res/values-vi/strings.xml +++ b/packages/PrintSpooler/res/values-vi/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Hiển thị hộp tìm kiếm"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Ẩn hộp tìm kiếm"</string> <string name="print_add_printer" msgid="1088656468360653455">"Thêm máy in"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Chọn máy in"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Bỏ qua máy in"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"Đã tìm thấy <xliff:g id="COUNT">%1$s</xliff:g> máy in"</item> <item quantity="other" msgid="6533817036607128241">"Đã tìm thấy <xliff:g id="COUNT">%1$s</xliff:g> máy in"</item> diff --git a/packages/PrintSpooler/res/values-zh-rCN/strings.xml b/packages/PrintSpooler/res/values-zh-rCN/strings.xml index 7e501f1..e43ea60 100644 --- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml +++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"搜索框已显示"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"搜索框已隐藏"</string> <string name="print_add_printer" msgid="1088656468360653455">"添加打印机"</string> + <string name="print_select_printer" msgid="7388760939873368698">"选择打印机"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"取消保存打印机"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"找到<xliff:g id="COUNT">%1$s</xliff:g>台打印机"</item> <item quantity="other" msgid="6533817036607128241">"找到<xliff:g id="COUNT">%1$s</xliff:g>台打印机"</item> diff --git a/packages/PrintSpooler/res/values-zh-rHK/strings.xml b/packages/PrintSpooler/res/values-zh-rHK/strings.xml index 3856c75..2c2422a9 100644 --- a/packages/PrintSpooler/res/values-zh-rHK/strings.xml +++ b/packages/PrintSpooler/res/values-zh-rHK/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"搜尋框已顯示"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"搜尋框已隱藏"</string> <string name="print_add_printer" msgid="1088656468360653455">"新增打印機"</string> + <string name="print_select_printer" msgid="7388760939873368698">"選取打印機"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"移除打印機"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"找到 <xliff:g id="COUNT">%1$s</xliff:g> 部打印機"</item> <item quantity="other" msgid="6533817036607128241">"找到 <xliff:g id="COUNT">%1$s</xliff:g> 部打印機"</item> diff --git a/packages/PrintSpooler/res/values-zh-rTW/strings.xml b/packages/PrintSpooler/res/values-zh-rTW/strings.xml index 81e0627..0fe88d9 100644 --- a/packages/PrintSpooler/res/values-zh-rTW/strings.xml +++ b/packages/PrintSpooler/res/values-zh-rTW/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"搜尋框已顯示"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"搜尋框已隱藏"</string> <string name="print_add_printer" msgid="1088656468360653455">"新增印表機"</string> + <string name="print_select_printer" msgid="7388760939873368698">"選取印表機"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"移除印表機"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"找到 <xliff:g id="COUNT">%1$s</xliff:g> 台印表機"</item> <item quantity="other" msgid="6533817036607128241">"找到 <xliff:g id="COUNT">%1$s</xliff:g> 台印表機"</item> diff --git a/packages/PrintSpooler/res/values-zu/strings.xml b/packages/PrintSpooler/res/values-zu/strings.xml index 03c499f..08e31e1 100644 --- a/packages/PrintSpooler/res/values-zu/strings.xml +++ b/packages/PrintSpooler/res/values-zu/strings.xml @@ -41,6 +41,8 @@ <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"Ibhokisi lokuhlola libonisiwe"</string> <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"Ibhokisi lokusesha lifihliwe"</string> <string name="print_add_printer" msgid="1088656468360653455">"Engeza iphrinta"</string> + <string name="print_select_printer" msgid="7388760939873368698">"Khetha iphrinta"</string> + <string name="print_forget_printer" msgid="5035287497291910766">"Khohlwa iphrinta"</string> <plurals name="print_search_result_count_utterance"> <item quantity="one" msgid="4484953260685964252">"<xliff:g id="COUNT">%1$s</xliff:g> iphrinta itholiwe"</item> <item quantity="other" msgid="6533817036607128241">"<xliff:g id="COUNT">%1$s</xliff:g> amaphrinta atholiwe"</item> diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java index 778fb4d..615d667 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java +++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java @@ -441,6 +441,7 @@ public final class PrintSpoolerService extends Service { private void removeObsoletePrintJobs() { synchronized (mLock) { + boolean persistState = false; final int printJobCount = mPrintJobs.size(); for (int i = printJobCount - 1; i >= 0; i--) { PrintJobInfo printJob = mPrintJobs.get(i); @@ -450,9 +451,12 @@ public final class PrintSpoolerService extends Service { Slog.i(LOG_TAG, "[REMOVE] " + printJob.getId().flattenToString()); } removePrintJobFileLocked(printJob.getId()); + persistState = true; } } - mPersistanceManager.writeStateLocked(); + if (persistState) { + mPersistanceManager.writeStateLocked(); + } } } @@ -799,6 +803,10 @@ public final class PrintSpoolerService extends Service { for (int j = 0; j < printJobCount; j++) { PrintJobInfo printJob = printJobs.get(j); + if (!shouldPersistPrintJob(printJob)) { + continue; + } + serializer.startTag(null, TAG_JOB); serializer.attribute(null, ATTR_ID, printJob.getId().flattenToString()); diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 09ac2da..8d6fe41 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -71,6 +71,9 @@ <!-- Keyguard --> <uses-permission android:name="android.permission.CONTROL_KEYGUARD" /> + <!-- Wifi Display --> + <uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" /> + <application android:persistent="true" android:allowClearUserData="false" diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_available.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_available.png Binary files differnew file mode 100644 index 0000000..1c3518a --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_available.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connected.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connected.png Binary files differnew file mode 100644 index 0000000..9dbc65e --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connected.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_0.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_0.png Binary files differnew file mode 100644 index 0000000..ddb002d --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_0.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_1.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_1.png Binary files differnew file mode 100644 index 0000000..43b7ef2 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_1.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_2.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_2.png Binary files differnew file mode 100644 index 0000000..1d8b7ee --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_cast_connecting_2.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_remote_display.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_remote_display.png Binary files differdeleted file mode 100644 index 02d7fda..0000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_remote_display.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_remote_display_connected.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_remote_display_connected.png Binary files differdeleted file mode 100644 index 263f07c..0000000 --- a/packages/SystemUI/res/drawable-hdpi/ic_qs_remote_display_connected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-hdpi/search_light_land.png b/packages/SystemUI/res/drawable-hdpi/search_light_land.png Binary files differnew file mode 100644 index 0000000..731f19b --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/search_light_land.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_available.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_available.png Binary files differnew file mode 100644 index 0000000..11b2134 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_available.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connected.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connected.png Binary files differnew file mode 100644 index 0000000..a858573 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connected.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_0.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_0.png Binary files differnew file mode 100644 index 0000000..04de5d7 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_0.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_1.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_1.png Binary files differnew file mode 100644 index 0000000..caea37e --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_1.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_2.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_2.png Binary files differnew file mode 100644 index 0000000..b66aa46 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_cast_connecting_2.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_remote_display.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_remote_display.png Binary files differdeleted file mode 100644 index 09ae409..0000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_remote_display.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_remote_display_connected.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_remote_display_connected.png Binary files differdeleted file mode 100644 index 780cfc8..0000000 --- a/packages/SystemUI/res/drawable-mdpi/ic_qs_remote_display_connected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-mdpi/search_light_land.png b/packages/SystemUI/res/drawable-mdpi/search_light_land.png Binary files differnew file mode 100644 index 0000000..a4d82f0 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/search_light_land.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_available.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_available.png Binary files differnew file mode 100644 index 0000000..10ebcd5 --- /dev/null +++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_available.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connected.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connected.png Binary files differnew file mode 100644 index 0000000..fef43b8 --- /dev/null +++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connected.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_0.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_0.png Binary files differnew file mode 100644 index 0000000..05e3267 --- /dev/null +++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_0.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_1.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_1.png Binary files differnew file mode 100644 index 0000000..ef42b27 --- /dev/null +++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_1.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_2.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_2.png Binary files differnew file mode 100644 index 0000000..fc1c95e --- /dev/null +++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_cast_connecting_2.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_remote_display.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_remote_display.png Binary files differdeleted file mode 100644 index 48f90ac..0000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_remote_display.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_remote_display_connected.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_remote_display_connected.png Binary files differdeleted file mode 100644 index 621c045..0000000 --- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_remote_display_connected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xhdpi/search_light_land.png b/packages/SystemUI/res/drawable-xhdpi/search_light_land.png Binary files differnew file mode 100644 index 0000000..b62c74e --- /dev/null +++ b/packages/SystemUI/res/drawable-xhdpi/search_light_land.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_available.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_available.png Binary files differnew file mode 100644 index 0000000..68b1b7c --- /dev/null +++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_available.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connected.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connected.png Binary files differnew file mode 100644 index 0000000..8a8f890 --- /dev/null +++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connected.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_0.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_0.png Binary files differnew file mode 100644 index 0000000..12d4a01 --- /dev/null +++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_0.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_1.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_1.png Binary files differnew file mode 100644 index 0000000..3cb4421 --- /dev/null +++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_1.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_2.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_2.png Binary files differnew file mode 100644 index 0000000..4620b3a --- /dev/null +++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_cast_connecting_2.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_remote_display.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_remote_display.png Binary files differdeleted file mode 100644 index b07be828..0000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_remote_display.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_remote_display_connected.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_remote_display_connected.png Binary files differdeleted file mode 100644 index f02d0ab..0000000 --- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_remote_display_connected.png +++ /dev/null diff --git a/packages/SystemUI/res/drawable-xxhdpi/search_light_land.png b/packages/SystemUI/res/drawable-xxhdpi/search_light_land.png Binary files differnew file mode 100644 index 0000000..f364577 --- /dev/null +++ b/packages/SystemUI/res/drawable-xxhdpi/search_light_land.png diff --git a/packages/SystemUI/res/drawable/ic_qs_cast_connecting.xml b/packages/SystemUI/res/drawable/ic_qs_cast_connecting.xml new file mode 100644 index 0000000..70db2a9 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_cast_connecting.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright 2013, 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. + */ +--> +<animation-list + xmlns:android="http://schemas.android.com/apk/res/android" + android:oneshot="false"> + <item android:drawable="@drawable/ic_qs_cast_connecting_0" android:duration="500" /> + <item android:drawable="@drawable/ic_qs_cast_connecting_1" android:duration="500" /> + <item android:drawable="@drawable/ic_qs_cast_connecting_2" android:duration="500" /> + <item android:drawable="@drawable/ic_qs_cast_connecting_1" android:duration="500" /> +</animation-list> diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml index aa365ae..5488a87 100644 --- a/packages/SystemUI/res/layout/navigation_bar.xml +++ b/packages/SystemUI/res/layout/navigation_bar.xml @@ -311,7 +311,7 @@ android:layout_height="80dp" android:layout_width="match_parent" android:layout_gravity="center_vertical" - android:src="@drawable/search_light" + android:src="@drawable/search_light_land" android:scaleType="center" android:visibility="gone" android:contentDescription="@string/accessibility_search_light" diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 6f0d857c..988d594 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nie gekoppel nie"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Geen netwerk nie"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi af"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi-skerm"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Draadlose aansig"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Saai na skerm uit"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Helderheid"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OUTO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netwerk word\ndalk gemonitor"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 686488e..ae0c650 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"አልተገናኘም"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ምንም አውታረ መረብ የለም"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ጠፍቷል"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"የWi-Fi ማሳያ"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"ገመድ አልባ ማሳያ"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"ማያ ገጽ ውሰድ"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"ብሩህነት"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ራስ-ሰር"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"አውታረ መረብ\nክትትል ሊደረግበት ይችላል"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 214daae..88b6762 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"ليست متصلة"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"لا تتوفر شبكة"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"إيقاف Wi-Fi"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"عرض Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"عرض شاشة لاسلكي"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"بث الشاشة"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"السطوع"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"تلقائي"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"قد تكون الشبكة\nخاضعة للرقابة"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 356e7df..b574e79 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -205,8 +205,8 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Няма падключэння"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Няма сеткi"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi адключаны"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Дысплей Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Бесправадны дысплей"</string> + <!-- no translation found for quick_settings_remote_display_no_connection_label (3319785626703585888) --> + <skip /> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Яркасць"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АЎТА"</string> <!-- no translation found for ssl_ca_cert_warning (9005954106902053641) --> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index c893490..1814c23 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Няма връзка"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Няма мрежа"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi е изключен"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Дисплей през Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Безжичен дисплей"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Екран за предаване"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Яркост"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТ."</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мрежата може\nда се наблюдава"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index f29b10e..ad7eb5d 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -198,8 +198,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Desconnectat"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No hi ha cap xarxa"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desconnectada"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Pantalla Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Pantalla sense fil"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Pantalla d\'emissió"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brillantor"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÀTICA"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"És possible que la xarxa\nestigui controlada"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 76a7201..c74f15c 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -198,8 +198,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nepřipojeno"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Žádná síť"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi vypnuta"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Displej přes Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Bezdrátový displej"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Vzdálená obrazovka"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Jas"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATICKY"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Síť může být\nmonitorována"</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 3f31217..3da7c6a 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ikke forbundet"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Intet netværk"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi slået fra"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Display"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Trådløs skærm"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Cast-skærm"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Lysstyrke"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netværket kan\nvære overvåget"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 444a555..0e1017b 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -198,8 +198,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nicht verbunden"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Kein Netz"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WLAN aus"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"WLAN-Display"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Kabellose Übertragung (WiDi)"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Bildschirm übertragen"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Helligkeit"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netzwerk wird\neventuell überwacht."</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 6be551c..1b6929c 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -198,8 +198,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Μη συνδεδεμένο"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Κανένα δίκτυο"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ανενεργό"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Οθόνη Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Ασύρματη οθόνη"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Μετάδοση οθόνης"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Φωτεινότητα"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ΑΥΤΟΜΑΤΗ"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Το δίκτυο μπορεί\nνα παρακολουθείται"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 93efc15..825692d 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Not Connected"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No Network"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Off"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Display"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Wireless Display"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Cast Screen"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brightness"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Network may\nbe monitored"</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 93efc15..825692d 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Not Connected"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No Network"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Off"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Display"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Wireless Display"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Cast Screen"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brightness"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Network may\nbe monitored"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 4c795cb..6202baf 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -198,8 +198,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Sin conexión"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Sin red"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desactivada"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Pantalla Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Pantalla inalámbrica"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Pantalla de Cast"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brillo"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Es posible que la red\nesté supervisada."</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 9814ae7..154c0ee 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"No conectado"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No hay red."</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desactivado"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Pantalla Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Pantalla inalámbrica"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Pantalla de Cast"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brillo"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"La red se\npuede supervisar"</string> diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml index 510cce2..fad777c 100644 --- a/packages/SystemUI/res/values-et-rEE/strings.xml +++ b/packages/SystemUI/res/values-et-rEE/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ühendus puudub"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Võrku pole"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WiFi-ühendus on väljas"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"WiFi-ekraan"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Juhtmeta ekraaniühendus"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Cast-ekraan"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Heledus"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAATNE"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Võrku võidakse\njälgida"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 4d2b1c4..5782975 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"متصل نیست"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"شبکهای موجود نیست"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi خاموش است"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Display"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"نمایش بدون سیم"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"فرستادن صفحه"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"روشنایی"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"خودکار"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ممکن است شبکه\nتحت نظارت باشد"</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 299a0a5..9a715e8 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ei yhteyttä"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ei verkkoa"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wifi-yhteys pois käytöstä"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wifi-näyttö"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Langaton näyttö"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Lähetysnäyttö"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Kirkkaus"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Verkkoa saatetaan\nvalvoa"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 2a53193..bb1dbf1 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -198,8 +198,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Non connecté"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Aucun réseau"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi désactivé"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Affichage Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Affichage sans fil"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Écran distant"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Luminosité"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATIQUE"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Le réseau peut\nêtre surveillé."</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 61260fe..a0eee35 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -198,8 +198,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Non connecté"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Aucun réseau"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi désactivé"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Display"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Affichage sans fil"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Écran sur lequel l\'affichage est diffusé"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Luminosité"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATIQUE"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Le réseau peut\nêtre surveillé."</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 44273b1..4b1c3bc 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"कनेक्ट नहीं है"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"कोई नेटवर्क नहीं"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi बंद"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi प्रदर्शन"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"वायरलेस डिस्प्ले"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"स्क्रीन कास्ट करें"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"स्क्रीन की रोशनी"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"स्वत:"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"नेटवर्क को\nमॉनीटर किया जा सकता है"</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 7384dd5..afed35c 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nije povezano"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nema mreže"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi isključen"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi zaslon"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Bežični prikaz"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Emitiranje zaslona"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Svjetlina"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATSKI"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Mreža se\nmožda prati"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 65605aa..aba5a88 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nincs kapcsolat"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nincs hálózat"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi kikapcsolva"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi kijelző"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Vezeték nélküli kijelző"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Képernyő tartalmának átküldése"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Fényerő"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"automatikus"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Lehet, hogy a\nhálózat felügyelt"</string> diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml index d2f5096..f5793c0 100644 --- a/packages/SystemUI/res/values-hy-rAM/strings.xml +++ b/packages/SystemUI/res/values-hy-rAM/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Միացված չէ"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ցանց չկա"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi-ը անջատված է"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi ցուցադրիչ"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Անլար էկրան"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Հեռակա էկրան"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Պայծառություն"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"Ինքնաշխատ"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Ցանցը կարող է\nվերահսկվել"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 32e7c42..0893599 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -176,7 +176,7 @@ <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string> <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode pesawat"</string> <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Mengisi baterai, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string> - <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Ditagih"</string> + <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Terisi"</string> <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string> <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Perangkat)"</string> <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Mati"</string> @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Tidak Tersambung"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tidak Ada Jaringan"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Mati"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Tampilan Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Layar Nirkabel"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Layar Transmisi"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Kecerahan"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATIS"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Jaringan bisa\ndiawasi"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index f8790bb..67ae18d 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -198,8 +198,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Non connesso"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nessuna rete"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi disattivato"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Display Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Visualizzazione wireless"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Trasmetti schermo"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Luminosità"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"La rete potrebbe\nessere monitorata"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 5dbe432..fe9c458 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"לא מחובר"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"אין רשת"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi כבוי"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"תצוגת Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"תצוגת Wi-Fi"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"העבר מסך"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"בהירות"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"אוטומטי"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ייתכן שהרשת\nמנוטרת"</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index d1ba2a8..13bea42 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -198,8 +198,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"接続されていません"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ネットワークなし"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi OFF"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fiディスプレイ"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"ワイヤレスディスプレイ"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"画面のキャスト"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"画面の明るさ"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ネットワークが監視される\n場合があります"</string> diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml index bd6e87f..67b29d6 100644 --- a/packages/SystemUI/res/values-ka-rGE/strings.xml +++ b/packages/SystemUI/res/values-ka-rGE/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"არ არის დაკავშირებული."</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ქსელი არ არის"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi გამორთულია"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi ეკრანი"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"უსადენო ეკრანი"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Cast Screen"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"განათება"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ავტომატურად"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"შესაძლოა ქსელზე\nმონიტორინგი ხორციელდებოდეს"</string> diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml index 20ee33b..4afc08b 100644 --- a/packages/SystemUI/res/values-km-rKH/strings.xml +++ b/packages/SystemUI/res/values-km-rKH/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"មិនបានតភ្ជាប់"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"គ្មានបណ្ដាញ"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"បិទវ៉ាយហ្វាយ"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"បង្ហាញវ៉ាយហ្វាយ"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"បង្ហាញបណ្ដាញឥតខ្សែ"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"ចាត់ថ្នាក់អេក្រង់"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"ពន្លឺ"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ស្វ័យប្រវត្តិ"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"បណ្ដាញអាច\nត្រូវបានត្រួតពិនិត្យ"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index cec56e5..ec8bdc1 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"연결되어 있지 않음"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"네트워크가 연결되지 않음"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi 꺼짐"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi 디스플레이"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"무선 디스플레이"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"화면 전송"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"밝기"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"자동"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"네트워크가\n모니터링될 수 있음"</string> diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml index f62dea2..766477f 100644 --- a/packages/SystemUI/res/values-lo-rLA/strings.xml +++ b/packages/SystemUI/res/values-lo-rLA/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"ບໍ່ໄດ້ເຊື່ອມຕໍ່"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ບໍ່ມີເຄືອຂ່າຍ"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ປິດ"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"ຈໍສະແດງຜົນ Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"ການສະແດງຜົນໄຮ້ສາຍ"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"ດຶງໜ້າຈໍ"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"ຄວາມແຈ້ງ"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ອັດຕະໂນມັດ"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ເຄືອຄ່າຍອາດ\nຖືກຕິດຕາມ"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index c38b653..4feeae2 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Neprisijungta"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tinklo nėra"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"„Wi-Fi“ išjungta"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"„Wi-Fi“ pateiktis"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Belaidis rodymas"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Perduoti ekraną"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Skaistis"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATINIS"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Tinklas gali\nbūti stebimas"</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index e969920..01d1108 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nav izveidots savienojums"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nav tīkla"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ir izslēgts"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi displejs"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Bezvadu attēlošana"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Apraides ekrāns"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Spilgtums"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMĀTISKI"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Tīkls var\ntikt uzraudzīts"</string> diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml index 72d92b5..d92407c 100644 --- a/packages/SystemUI/res/values-mn-rMN/strings.xml +++ b/packages/SystemUI/res/values-mn-rMN/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Холбогдоогүй"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Сүлжээгүй"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi унтарсан"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Дэлгэц"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Утасгүй дэлгэц"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Дамжуулах дэлгэц"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Тодрол"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТОМАТ"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Сүлжээ хянагдаж\nбайж болзошгүй"</string> diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml index dff3279..58613fd 100644 --- a/packages/SystemUI/res/values-ms-rMY/strings.xml +++ b/packages/SystemUI/res/values-ms-rMY/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Tidak Disambungkan"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tiada Rangkaian"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Dimatikan"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Paparan Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Paparan Wayarles"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Skrin Cast"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Kecerahan"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Rangkaian mungkin\nboleh dipantau"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 66320ce..f75730e 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ikke tilkoblet"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ingen nettverk"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi er av"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi-skjerm"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Trådløs skjerm"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Send skjermen"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Lysstyrke"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Nettverket kan\nvære overvåket"</string> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 9aa7e75..a05f9c5 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Niet verbonden"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Geen netwerk"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wifi uit"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wifi-weergave"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Draadloze weergave"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Scherm sturen"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Helderheid"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATISCH"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netwerk kan\nworden gecontroleerd"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 3fe07e7..83e3c43 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Brak połączenia"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Brak sieci"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wyłącz Wi-Fi"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wyświetlacz Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Wyświetlacz bezprzewodowy"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Ekran Cast"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Jasność"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATYCZNA"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Sieć może być\nmonitorowana"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index 22eda90..4e318d7 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Não Ligado"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Sem Rede"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Desligado"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Visualização Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Display Sem Fios"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Transmitir ecrã"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brilho"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"A rede pode ser\nmonitorizada"</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 351965f..f97da2f 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -198,8 +198,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Não conectado"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Sem rede"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desligado"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Display"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Display sem fio"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Transmitir tela"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brilho"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"A rede pode estar\nsob monitoração"</string> diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml index 9e1c9b8..5bc11e9 100644 --- a/packages/SystemUI/res/values-rm/strings.xml +++ b/packages/SystemUI/res/values-rm/strings.xml @@ -362,9 +362,7 @@ <skip /> <!-- no translation found for quick_settings_wifi_off_label (7558778100843885864) --> <skip /> - <!-- no translation found for quick_settings_wifi_display_label (6893592964463624333) --> - <skip /> - <!-- no translation found for quick_settings_wifi_display_no_connection_label (2355298740765736918) --> + <!-- no translation found for quick_settings_remote_display_no_connection_label (372107699274391290) --> <skip /> <!-- no translation found for quick_settings_brightness_dialog_title (8599674057673605368) --> <skip /> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 7415128..168369d 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Neconectat"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nicio reţea"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi deconectat"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Afişaj Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Ecran wireless"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Ecran de afișare a transmisiunii"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Luminozitate"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAT"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Rețeaua poate\nfi monitorizată"</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index a587dec..96e6e13 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -200,8 +200,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Нет соединения"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Нет сети"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi выкл."</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Проектор Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Wi-Fi-монитор"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Wi-Fi-монитор"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Яркость"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТОНАСТРОЙКА"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Действия в сети\nмогут отслеживаться"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 0b82843..60e4dc2 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -198,8 +198,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nepripojené"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Žiadna sieť"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Sieť Wi-Fi je vypnutá"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Obrazovka Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Bezdrôtový displej"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Vzdialená obrazovka"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Jas"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATICKY"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Sieť môže byť\nmonitorovaná"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 6699440..2f90aeb 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Povezava ni vzpostavljena"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ni omrežja"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi izklopljen"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Zaslon Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Prikaz brezžičnih naprav"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Zaslon za predvajanje"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Svetlost"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"SAMODEJNO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Omrežje je\nlahko spremljano"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 4e990d1..33607f2 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Веза није успостављена"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Нема мреже"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi је искључен"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi екран"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Бежични екран"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Пребаци екран"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Осветљеност"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АУТОМАТСКА"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мрежа се можда\nнадгледа"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 06eccfc..b49b5c9 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ej ansluten"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Inget nätverk"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi av"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi-skärm"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Trådlös skärm"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Överför skärmen"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Ljusstyrka"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Nätverket kan\nvara övervakat"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 6bd8632..ac025fd 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -194,8 +194,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Haijaunganishwa"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Hakuna Mtandao"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Imezimwa"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Onyesho la Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Uonyeshaji Pasiwaya"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Utumaji wa Skrini"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Ung\'avu"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"KIOTOMATIKI"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Huenda mtandao\nunafuatiliwa"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 6893694..65b075a 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"ไม่ได้เชื่อมต่อ"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ไม่มีเครือข่าย"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"ปิด WiFi"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"การแสดงผล WiFi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"จอแสดงผลไร้สาย"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"ส่งหน้าจอ"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"ความสว่าง"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"อัตโนมัติ"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"เครือข่ายอาจ\nถูกตรวจสอบ"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 6aa4b47..4ac1b53 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Hindi Nakakonekta"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Walang Network"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Naka-off ang Wi-Fi"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Display ng Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Wireless Display"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"I-cast ang Screen"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brightness"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Maaaring\nsinusubaybayan ang network"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 964371f..a15e375 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Bağlı Değil"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ağ yok"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Kablosuz Kapalı"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Kablosuz Ekran"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Kablosuz Ekran"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Yayınlama Ekranı"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Parlaklık"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATİK"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Ağ izleniyor\nolabilir"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index f502691..439c3d7 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Не під’єднано."</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Немає мережі"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi вимкнено"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Відображення Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Бездротове відображення"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Транслювати екран"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Яскравість"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТО"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мережа може\nвідстежуватися"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 707f2d8..34d1414 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Chưa được kết nối"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Không có mạng nào"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Tắt Wi-Fi"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Hiển thị Wi-Fi"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Hiển thị không dây"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Truyền màn hình"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Độ sáng"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"TỰ ĐỘNG"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Mạng có thể\nđược giám sát"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 87f1893..f759662 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -198,8 +198,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"未连接"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"无网络"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WLAN 已关闭"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"WLAN 显示"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"无线显示"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"投射屏幕"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自动"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"网络可能会\n受到监控"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 1007f85..bf5ae35 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -198,8 +198,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"未連線"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"沒有網絡"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi 關閉"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Display"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"無線顯示"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"放送螢幕"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"網絡可能會\n受到監控"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index edd6fd2..b1f99f5 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -198,8 +198,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"未連線"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"沒有網路"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"關閉 Wi-Fi"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi 顯示裝置"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"無線螢幕分享"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"投放螢幕"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"網路可能\n受到監控"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index d43ccfc..f284b7c 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -196,8 +196,7 @@ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Akuxhunyiwe"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ayikho inethiwekhi"</string> <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"I-Wi-Fi icimile"</string> - <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Ukuboniswa kwe-Wi-"</string> - <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Ukubonisa okungenazintambo"</string> + <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Isikrini sabalingisi"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Ukugqama"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OKUZENZAKALELAYO"</string> <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Kungenzeka inethiwekhi\niqashiwe"</string> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index e6fcdff..e36ca8e 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -490,10 +490,8 @@ <string name="quick_settings_wifi_no_network">No Network</string> <!-- QuickSettings: Wifi (Off) [CHAR LIMIT=NONE] --> <string name="quick_settings_wifi_off_label">Wi-Fi Off</string> - <!-- QuickSettings: Wifi display [CHAR LIMIT=NONE] --> - <string name="quick_settings_wifi_display_label">Wi-Fi Display</string> - <!-- QuickSettings: Wifi display [CHAR LIMIT=NONE] --> - <string name="quick_settings_wifi_display_no_connection_label">Wireless Display</string> + <!-- QuickSettings: Remote display [CHAR LIMIT=NONE] --> + <string name="quick_settings_remote_display_no_connection_label">Cast Screen</string> <!-- QuickSettings: Brightness dialog title [CHAR LIMIT=NONE] --> <string name="quick_settings_brightness_dialog_title">Brightness</string> <!-- QuickSettings: Brightness dialog auto brightness button [CHAR LIMIT=NONE] --> diff --git a/packages/SystemUI/src/com/android/systemui/DessertCase.java b/packages/SystemUI/src/com/android/systemui/DessertCase.java index dd4c018..d797e38 100644 --- a/packages/SystemUI/src/com/android/systemui/DessertCase.java +++ b/packages/SystemUI/src/com/android/systemui/DessertCase.java @@ -36,7 +36,8 @@ public class DessertCase extends Activity { if (pm.getComponentEnabledSetting(cn) != PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { Slog.v("DessertCase", "ACHIEVEMENT UNLOCKED"); pm.setComponentEnabledSetting(cn, - PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0); + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP); } mView = new DessertCaseView(this); diff --git a/packages/SystemUI/src/com/android/systemui/DessertCaseView.java b/packages/SystemUI/src/com/android/systemui/DessertCaseView.java index 6fce732..4147155 100644 --- a/packages/SystemUI/src/com/android/systemui/DessertCaseView.java +++ b/packages/SystemUI/src/com/android/systemui/DessertCaseView.java @@ -496,7 +496,6 @@ public class DessertCaseView extends FrameLayout { } public static class RescalingContainer extends FrameLayout { - private static final int SYSTEM_UI_MODE_800 = 0x00000800; private DessertCaseView mView; private float mDarkness; @@ -509,7 +508,7 @@ public class DessertCaseView extends FrameLayout { | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | SYSTEM_UI_MODE_800 + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY ); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java b/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java index 9839fe9..7d3e870 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java @@ -38,7 +38,7 @@ public class AnimatedImageView extends ImageView { } private void updateAnim() { - Drawable drawable = getDrawable(); + Drawable drawable = mAttached ? getDrawable() : null; if (mAttached && mAnim != null) { mAnim.stop(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 607ce41..bbac4ef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -2105,9 +2105,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode { } public void tickerHalting() { - mStatusBarContents.setVisibility(View.VISIBLE); + if (mStatusBarContents.getVisibility() != View.VISIBLE) { + mStatusBarContents.setVisibility(View.VISIBLE); + mStatusBarContents + .startAnimation(loadAnim(com.android.internal.R.anim.fade_in, null)); + } mTickerView.setVisibility(View.GONE); - mStatusBarContents.startAnimation(loadAnim(com.android.internal.R.anim.fade_in, null)); // we do not animate the ticker away at this point, just get rid of it (b/6992707) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java index 37504fb..e7b8fa1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java @@ -37,9 +37,8 @@ import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import android.graphics.drawable.LevelListDrawable; import android.hardware.display.DisplayManager; -import android.hardware.display.WifiDisplayStatus; +import android.media.MediaRouter; import android.net.wifi.WifiManager; import android.os.AsyncTask; import android.os.Handler; @@ -62,6 +61,7 @@ import android.view.WindowManagerGlobal; import android.widget.ImageView; import android.widget.TextView; +import com.android.internal.app.MediaRouteDialogPresenter; import com.android.systemui.R; import com.android.systemui.statusbar.phone.QuickSettingsModel.ActivityState; import com.android.systemui.statusbar.phone.QuickSettingsModel.BluetoothState; @@ -92,9 +92,7 @@ class QuickSettings { private QuickSettingsModel mModel; private ViewGroup mContainerView; - private DisplayManager mDisplayManager; private DevicePolicyManager mDevicePolicyManager; - private WifiDisplayStatus mWifiDisplayStatus; private PhoneStatusBar mStatusBarService; private BluetoothState mBluetoothState; private BluetoothAdapter mBluetoothAdapter; @@ -118,13 +116,11 @@ class QuickSettings { new ArrayList<QuickSettingsTileView>(); public QuickSettings(Context context, QuickSettingsContainerView container) { - mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); mDevicePolicyManager = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); mContext = context; mContainerView = container; mModel = new QuickSettingsModel(context); - mWifiDisplayStatus = new WifiDisplayStatus(); mBluetoothState = new QuickSettingsModel.BluetoothState(); mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); @@ -171,7 +167,6 @@ class QuickSettings { mLocationController = locationController; setupQuickSettings(); - updateWifiDisplayStatus(); updateResources(); applyLocationEnabledStatus(); @@ -314,11 +309,19 @@ class QuickSettings { collapsePanels(); final UserManager um = UserManager.get(mContext); if (um.getUsers(true).size() > 1) { - try { - WindowManagerGlobal.getWindowManagerService().lockNow(null); - } catch (RemoteException e) { - Log.e(TAG, "Couldn't show user switcher", e); - } + // Since keyguard and systemui were merged into the same process to save + // memory, they share the same Looper and graphics context. As a result, + // there's no way to allow concurrent animation while keyguard inflates. + // The workaround is to add a slight delay to allow the animation to finish. + mHandler.postDelayed(new Runnable() { + public void run() { + try { + WindowManagerGlobal.getWindowManagerService().lockNow(null); + } catch (RemoteException e) { + Log.e(TAG, "Couldn't show user switcher", e); + } + } + }, 400); // TODO: ideally this would be tied to the collapse of the panel } else { Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent( mContext, v, ContactsContract.Profile.CONTENT_URI, @@ -668,20 +671,33 @@ class QuickSettings { }); parent.addView(alarmTile); - // Wifi Display - QuickSettingsBasicTile wifiDisplayTile + // Remote Display + QuickSettingsBasicTile remoteDisplayTile = new QuickSettingsBasicTile(mContext); - wifiDisplayTile.setImageResource(R.drawable.ic_qs_remote_display); - wifiDisplayTile.setOnClickListener(new View.OnClickListener() { + remoteDisplayTile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - startSettingsActivity(android.provider.Settings.ACTION_WIFI_DISPLAY_SETTINGS); + collapsePanels(); + + final Dialog[] dialog = new Dialog[1]; + dialog[0] = MediaRouteDialogPresenter.createDialog(mContext, + MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, + new View.OnClickListener() { + @Override + public void onClick(View v) { + dialog[0].dismiss(); + startSettingsActivity( + android.provider.Settings.ACTION_WIFI_DISPLAY_SETTINGS); + } + }); + dialog[0].getWindow().setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY); + dialog[0].show(); } }); - mModel.addWifiDisplayTile(wifiDisplayTile, - new QuickSettingsModel.BasicRefreshCallback(wifiDisplayTile) + mModel.addRemoteDisplayTile(remoteDisplayTile, + new QuickSettingsModel.BasicRefreshCallback(remoteDisplayTile) .setShowWhenEnabled(true)); - parent.addView(wifiDisplayTile); + parent.addView(remoteDisplayTile); if (SHOW_IME_TILE || DEBUG_GONE_TILES) { // IME @@ -816,15 +832,6 @@ class QuickSettings { dialog.show(); } - private void updateWifiDisplayStatus() { - mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus(); - applyWifiDisplayStatus(); - } - - private void applyWifiDisplayStatus() { - mModel.onWifiDisplayStateChanged(mWifiDisplayStatus); - } - private void applyBluetoothStatus() { mModel.onBluetoothStateChange(mBluetoothState); } @@ -848,12 +855,7 @@ class QuickSettings { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); - if (DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED.equals(action)) { - WifiDisplayStatus status = (WifiDisplayStatus)intent.getParcelableExtra( - DisplayManager.EXTRA_WIFI_DISPLAY_STATUS); - mWifiDisplayStatus = status; - applyWifiDisplayStatus(); - } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { + if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); mBluetoothState.enabled = (state == BluetoothAdapter.STATE_ON); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java index 15d655c..e1a20ec 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java @@ -27,7 +27,8 @@ import android.content.pm.PackageManager; import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.drawable.Drawable; -import android.hardware.display.WifiDisplayStatus; +import android.media.MediaRouter; +import android.media.MediaRouter.RouteInfo; import android.net.ConnectivityManager; import android.os.Handler; import android.os.UserHandle; @@ -57,7 +58,6 @@ class QuickSettingsModel implements BluetoothStateChangeCallback, BrightnessStateChangeCallback, RotationLockControllerCallback, LocationSettingsChangeCallback { - // Sett InputMethoManagerService private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher"; @@ -199,6 +199,30 @@ class QuickSettingsModel implements BluetoothStateChangeCallback, } } + /** Callback for changes to remote display routes. */ + private class RemoteDisplayRouteCallback extends MediaRouter.SimpleCallback { + @Override + public void onRouteAdded(MediaRouter router, RouteInfo route) { + updateRemoteDisplays(); + } + @Override + public void onRouteChanged(MediaRouter router, RouteInfo route) { + updateRemoteDisplays(); + } + @Override + public void onRouteRemoved(MediaRouter router, RouteInfo route) { + updateRemoteDisplays(); + } + @Override + public void onRouteSelected(MediaRouter router, int type, RouteInfo route) { + updateRemoteDisplays(); + } + @Override + public void onRouteUnselected(MediaRouter router, int type, RouteInfo route) { + updateRemoteDisplays(); + } + } + private final Context mContext; private final Handler mHandler; private final CurrentUserTracker mUserTracker; @@ -206,6 +230,9 @@ class QuickSettingsModel implements BluetoothStateChangeCallback, private final BugreportObserver mBugreportObserver; private final BrightnessObserver mBrightnessObserver; + private final MediaRouter mMediaRouter; + private final RemoteDisplayRouteCallback mRemoteDisplayRouteCallback; + private final boolean mHasMobileData; private QuickSettingsTileView mUserTile; @@ -228,9 +255,9 @@ class QuickSettingsModel implements BluetoothStateChangeCallback, private RefreshCallback mWifiCallback; private WifiState mWifiState = new WifiState(); - private QuickSettingsTileView mWifiDisplayTile; - private RefreshCallback mWifiDisplayCallback; - private State mWifiDisplayState = new State(); + private QuickSettingsTileView mRemoteDisplayTile; + private RefreshCallback mRemoteDisplayCallback; + private State mRemoteDisplayState = new State(); private QuickSettingsTileView mRSSITile; private RefreshCallback mRSSICallback; @@ -278,12 +305,14 @@ class QuickSettingsModel implements BluetoothStateChangeCallback, mContext = context; mHandler = new Handler(); mUserTracker = new CurrentUserTracker(mContext) { + @Override public void onUserSwitched(int newUserId) { mBrightnessObserver.startObserving(); refreshRotationLockTile(); onBrightnessLevelChanged(); onNextAlarmChanged(); onBugreportChanged(); + rebindMediaRouterAsCurrentUser(); } }; @@ -294,6 +323,11 @@ class QuickSettingsModel implements BluetoothStateChangeCallback, mBrightnessObserver = new BrightnessObserver(mHandler); mBrightnessObserver.startObserving(); + mMediaRouter = (MediaRouter)context.getSystemService(Context.MEDIA_ROUTER_SERVICE); + rebindMediaRouterAsCurrentUser(); + + mRemoteDisplayRouteCallback = new RemoteDisplayRouteCallback(); + ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); mHasMobileData = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); @@ -621,24 +655,64 @@ class QuickSettingsModel implements BluetoothStateChangeCallback, mBugreportCallback.refreshView(mBugreportTile, mBugreportState); } - // Wifi Display - void addWifiDisplayTile(QuickSettingsTileView view, RefreshCallback cb) { - mWifiDisplayTile = view; - mWifiDisplayCallback = cb; + // Remote Display + void addRemoteDisplayTile(QuickSettingsTileView view, RefreshCallback cb) { + mRemoteDisplayTile = view; + mRemoteDisplayCallback = cb; + final int[] count = new int[1]; + mRemoteDisplayTile.setOnPrepareListener(new QuickSettingsTileView.OnPrepareListener() { + @Override + public void onPrepare() { + mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, + mRemoteDisplayRouteCallback, + MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY); + updateRemoteDisplays(); + } + @Override + public void onUnprepare() { + mMediaRouter.removeCallback(mRemoteDisplayRouteCallback); + } + }); + + updateRemoteDisplays(); } - public void onWifiDisplayStateChanged(WifiDisplayStatus status) { - mWifiDisplayState.enabled = - (status.getFeatureState() == WifiDisplayStatus.FEATURE_STATE_ON); - if (status.getActiveDisplay() != null) { - mWifiDisplayState.label = status.getActiveDisplay().getFriendlyDisplayName(); - mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display_connected; + + private void rebindMediaRouterAsCurrentUser() { + mMediaRouter.rebindAsUser(mUserTracker.getCurrentUserId()); + } + + private void updateRemoteDisplays() { + MediaRouter.RouteInfo connectedRoute = mMediaRouter.getSelectedRoute( + MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY); + boolean enabled = connectedRoute != null + && connectedRoute.matchesTypes(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY); + boolean connecting; + if (enabled) { + connecting = connectedRoute.isConnecting(); } else { - mWifiDisplayState.label = mContext.getString( - R.string.quick_settings_wifi_display_no_connection_label); - mWifiDisplayState.iconId = R.drawable.ic_qs_remote_display; + connectedRoute = null; + connecting = false; + final int count = mMediaRouter.getRouteCount(); + for (int i = 0; i < count; i++) { + MediaRouter.RouteInfo route = mMediaRouter.getRouteAt(i); + if (route.matchesTypes(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY)) { + enabled = true; + break; + } + } } - mWifiDisplayCallback.refreshView(mWifiDisplayTile, mWifiDisplayState); + mRemoteDisplayState.enabled = enabled; + if (connectedRoute != null) { + mRemoteDisplayState.label = connectedRoute.getName().toString(); + mRemoteDisplayState.iconId = connecting ? + R.drawable.ic_qs_cast_connecting : R.drawable.ic_qs_cast_connected; + } else { + mRemoteDisplayState.label = mContext.getString( + R.string.quick_settings_remote_display_no_connection_label); + mRemoteDisplayState.iconId = R.drawable.ic_qs_cast_available; + } + mRemoteDisplayCallback.refreshView(mRemoteDisplayTile, mRemoteDisplayState); } // IME diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsTileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsTileView.java index 3d520f7..ad18294 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsTileView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsTileView.java @@ -21,6 +21,7 @@ import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewParent; import android.widget.FrameLayout; /** @@ -31,14 +32,14 @@ class QuickSettingsTileView extends FrameLayout { private int mContentLayoutId; private int mColSpan; - private int mRowSpan; + private boolean mPrepared; + private OnPrepareListener mOnPrepareListener; public QuickSettingsTileView(Context context, AttributeSet attrs) { super(context, attrs); mContentLayoutId = -1; mColSpan = 1; - mRowSpan = 1; } void setColumnSpan(int span) { @@ -77,4 +78,72 @@ class QuickSettingsTileView extends FrameLayout { } super.setVisibility(vis); } + + public void setOnPrepareListener(OnPrepareListener listener) { + if (mOnPrepareListener != listener) { + mOnPrepareListener = listener; + mPrepared = false; + post(new Runnable() { + @Override + public void run() { + updatePreparedState(); + } + }); + } + } + + @Override + protected void onVisibilityChanged(View changedView, int visibility) { + super.onVisibilityChanged(changedView, visibility); + updatePreparedState(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + updatePreparedState(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + updatePreparedState(); + } + + private void updatePreparedState() { + if (mOnPrepareListener != null) { + if (isParentVisible()) { + if (!mPrepared) { + mPrepared = true; + mOnPrepareListener.onPrepare(); + } + } else if (mPrepared) { + mPrepared = false; + mOnPrepareListener.onUnprepare(); + } + } + } + + private boolean isParentVisible() { + if (!isAttachedToWindow()) { + return false; + } + for (ViewParent current = getParent(); current instanceof View; + current = current.getParent()) { + View view = (View)current; + if (view.getVisibility() != VISIBLE) { + return false; + } + } + return true; + } + + /** + * Called when the view's parent becomes visible or invisible to provide + * an opportunity for the client to provide new content. + */ + public interface OnPrepareListener { + void onPrepare(); + void onUnprepare(); + } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java index dca5e41..6eb88be 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java @@ -22,7 +22,7 @@ import android.content.res.TypedArray; import android.graphics.Canvas; import android.os.SystemClock; import android.util.AttributeSet; -import android.util.Log; +import android.util.Slog; import android.view.MotionEvent; import android.view.View; @@ -75,7 +75,7 @@ public class DeadZone extends View { mVertical = (index == VERTICAL); if (DEBUG) - Log.v(TAG, this + " size=[" + mSizeMin + "-" + mSizeMax + "] hold=" + mHold + Slog.v(TAG, this + " size=[" + mSizeMin + "-" + mSizeMax + "] hold=" + mHold + (mVertical ? " vertical" : " horizontal")); setFlashOnTouchCapture(context.getResources().getBoolean(R.bool.config_dead_zone_flash)); @@ -106,7 +106,7 @@ public class DeadZone extends View { @Override public boolean onTouchEvent(MotionEvent event) { if (DEBUG) { - Log.v(TAG, this + " onTouch: " + MotionEvent.actionToString(event.getAction())); + Slog.v(TAG, this + " onTouch: " + MotionEvent.actionToString(event.getAction())); } final int action = event.getAction(); @@ -114,12 +114,12 @@ public class DeadZone extends View { poke(event); } else if (action == MotionEvent.ACTION_DOWN) { if (DEBUG) { - Log.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY()); + Slog.v(TAG, this + " ACTION_DOWN: " + event.getX() + "," + event.getY()); } int size = (int) getSize(event.getEventTime()); if ((mVertical && event.getX() < size) || event.getY() < size) { if (CHATTY) { - Log.v(TAG, "consuming errant click: (" + event.getX() + "," + event.getY() + ")"); + Slog.v(TAG, "consuming errant click: (" + event.getX() + "," + event.getY() + ")"); } if (mShouldFlash) { post(mDebugFlash); @@ -134,7 +134,7 @@ public class DeadZone extends View { public void poke(MotionEvent event) { mLastPokeTime = event.getEventTime(); if (DEBUG) - Log.v(TAG, "poked! size=" + getSize(mLastPokeTime)); + Slog.v(TAG, "poked! size=" + getSize(mLastPokeTime)); if (mShouldFlash) postInvalidate(); } diff --git a/policy/src/com/android/internal/policy/impl/BarController.java b/policy/src/com/android/internal/policy/impl/BarController.java index c38ad04..0ce4b12 100644 --- a/policy/src/com/android/internal/policy/impl/BarController.java +++ b/policy/src/com/android/internal/policy/impl/BarController.java @@ -37,8 +37,9 @@ public class BarController { private static final boolean DEBUG = false; private static final int TRANSIENT_BAR_NONE = 0; - private static final int TRANSIENT_BAR_SHOWING = 1; - private static final int TRANSIENT_BAR_HIDING = 2; + private static final int TRANSIENT_BAR_SHOW_REQUESTED = 1; + private static final int TRANSIENT_BAR_SHOWING = 2; + private static final int TRANSIENT_BAR_HIDING = 3; private static final int TRANSLUCENT_ANIMATION_DELAY_MS = 1000; @@ -73,13 +74,9 @@ public class BarController { mWin = win; } - public boolean isHidden() { - return mState == StatusBarManager.WINDOW_STATE_HIDDEN; - } - public void showTransient() { if (mWin != null) { - setTransientBarState(TRANSIENT_BAR_SHOWING); + setTransientBarState(TRANSIENT_BAR_SHOW_REQUESTED); } } @@ -87,6 +84,10 @@ public class BarController { return mTransientBarState == TRANSIENT_BAR_SHOWING; } + public boolean isTransientShowRequested() { + return mTransientBarState == TRANSIENT_BAR_SHOW_REQUESTED; + } + public boolean wasRecentlyTranslucent() { return (SystemClock.uptimeMillis() - mLastTranslucent) < TRANSLUCENT_ANIMATION_DELAY_MS; } @@ -198,6 +199,9 @@ public class BarController { if (mTransientBarState == TRANSIENT_BAR_SHOWING) { if (DEBUG) Slog.d(mTag, "Not showing transient bar, already shown"); return false; + } else if (mTransientBarState == TRANSIENT_BAR_SHOW_REQUESTED) { + if (DEBUG) Slog.d(mTag, "Not showing transient bar, already requested"); + return false; } else if (mWin == null) { if (DEBUG) Slog.d(mTag, "Not showing transient bar, bar doesn't exist"); return false; @@ -211,12 +215,13 @@ public class BarController { public int updateVisibilityLw(boolean transientAllowed, int oldVis, int vis) { if (mWin == null) return vis; - if (mTransientBarState == TRANSIENT_BAR_SHOWING) { // transient bar requested + if (isTransientShowing() || isTransientShowRequested()) { // transient bar requested if (transientAllowed) { vis |= mTransientFlag; if ((oldVis & mTransientFlag) == 0) { vis |= mUnhideFlag; // tell sysui we're ready to unhide } + setTransientBarState(TRANSIENT_BAR_SHOWING); // request accepted } else { setTransientBarState(TRANSIENT_BAR_NONE); // request denied } @@ -254,6 +259,7 @@ public class BarController { private static String transientBarStateToString(int state) { if (state == TRANSIENT_BAR_HIDING) return "TRANSIENT_BAR_HIDING"; if (state == TRANSIENT_BAR_SHOWING) return "TRANSIENT_BAR_SHOWING"; + if (state == TRANSIENT_BAR_SHOW_REQUESTED) return "TRANSIENT_BAR_SHOW_REQUESTED"; if (state == TRANSIENT_BAR_NONE) return "TRANSIENT_BAR_NONE"; throw new IllegalArgumentException("Unknown state " + state); } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index faca949..c33bd35 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -3468,6 +3468,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } // Maintain fullscreen layout until incoming animation is complete. topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw(); + // Transient status bar on the lockscreen is not allowed + if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) { + mStatusBarController.updateVisibilityLw(false /*transientAllowed*/, + mLastSystemUiFlags, mLastSystemUiFlags); + } } else if (mTopFullscreenOpaqueWindowState != null) { if (localLOGV) { Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() @@ -5158,9 +5163,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { mNavigationBar != null && hideNavBarSysui && immersiveSticky; - boolean denyTransientStatus = mStatusBarController.isTransientShowing() + boolean denyTransientStatus = mStatusBarController.isTransientShowRequested() && !transientStatusBarAllowed && hideStatusBarSysui; - boolean denyTransientNav = mNavigationBarController.isTransientShowing() + boolean denyTransientNav = mNavigationBarController.isTransientShowRequested() && !transientNavBarAllowed; if (denyTransientStatus || denyTransientNav) { // clear the clearable flags instead diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java index bf22e2f..1357462 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java @@ -40,6 +40,14 @@ public class KeyguardServiceDelegate { private KeyguardState mKeyguardState = new KeyguardState(); /* package */ static final class KeyguardState { + KeyguardState() { + // Assume keyguard is showing and secure until we know for sure. This is here in + // the event something checks before the service is actually started. + // KeyguardService itself should default to this state until the real state is known. + showing = true; + showingAndNotHidden = true; + secure = true; + } boolean showing; boolean showingAndNotHidden; boolean inputRestricted; diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index a04ee14..baef607 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -46,6 +46,8 @@ import android.content.pm.IPackageInstallObserver; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; import android.content.pm.Signature; import android.content.pm.PackageManager.NameNotFoundException; import android.database.ContentObserver; @@ -146,6 +148,7 @@ class BackupManagerService extends IBackupManager.Stub { static final boolean COMPRESS_FULL_BACKUPS = true; // should be true in production static final String SHARED_BACKUP_AGENT_PACKAGE = "com.android.sharedstoragebackup"; + static final String SERVICE_ACTION_TRANSPORT_HOST = "android.backup.TRANSPORT_HOST"; // How often we perform a backup pass. Privileged external callers can // trigger an immediate pass. @@ -251,10 +254,13 @@ class BackupManagerService extends IBackupManager.Stub { volatile boolean mClearingData; // Transport bookkeeping + final HashMap<String,String> mTransportNames + = new HashMap<String,String>(); // component name -> registration name final HashMap<String,IBackupTransport> mTransports - = new HashMap<String,IBackupTransport>(); + = new HashMap<String,IBackupTransport>(); // registration name -> binder + final ArrayList<TransportConnection> mTransportConnections + = new ArrayList<TransportConnection>(); String mCurrentTransport; - IBackupTransport mLocalTransport, mGoogleTransport; ActiveRestoreSession mActiveRestoreSession; // Watch the device provisioning operation during setup @@ -815,13 +821,7 @@ class BackupManagerService extends IBackupManager.Stub { } // Set up our transport options and initialize the default transport - // TODO: Have transports register themselves somehow? // TODO: Don't create transports that we don't need to? - mLocalTransport = new LocalTransport(context); // This is actually pretty cheap - ComponentName localName = new ComponentName(context, LocalTransport.class); - registerTransport(localName.flattenToShortString(), mLocalTransport); - - mGoogleTransport = null; mCurrentTransport = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.BACKUP_TRANSPORT); if ("".equals(mCurrentTransport)) { @@ -829,28 +829,43 @@ class BackupManagerService extends IBackupManager.Stub { } if (DEBUG) Slog.v(TAG, "Starting with transport " + mCurrentTransport); - // Attach to the Google backup transport. When this comes up, it will set - // itself as the current transport because we explicitly reset mCurrentTransport - // to null. - ComponentName transportComponent = new ComponentName("com.google.android.backup", - "com.google.android.backup.BackupTransportService"); - try { - // If there's something out there that is supposed to be the Google - // backup transport, make sure it's legitimately part of the OS build - // and not an app lying about its package name. - ApplicationInfo info = mPackageManager.getApplicationInfo( - transportComponent.getPackageName(), 0); - if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { - if (DEBUG) Slog.v(TAG, "Binding to Google transport"); - Intent intent = new Intent().setComponent(transportComponent); - context.bindServiceAsUser(intent, mGoogleConnection, Context.BIND_AUTO_CREATE, - UserHandle.OWNER); - } else { - Slog.w(TAG, "Possible Google transport spoof: ignoring " + info); + // Find transport hosts and bind to their services + Intent transportServiceIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST); + List<ResolveInfo> hosts = mPackageManager.queryIntentServicesAsUser( + transportServiceIntent, 0, UserHandle.USER_OWNER); + if (DEBUG) { + Slog.v(TAG, "Found transports: " + ((hosts == null) ? "null" : hosts.size())); + } + if (hosts != null) { + if (MORE_DEBUG) { + for (int i = 0; i < hosts.size(); i++) { + ServiceInfo info = hosts.get(i).serviceInfo; + Slog.v(TAG, " " + info.packageName + "/" + info.name); + } + } + for (int i = 0; i < hosts.size(); i++) { + try { + ServiceInfo info = hosts.get(i).serviceInfo; + PackageInfo packInfo = mPackageManager.getPackageInfo(info.packageName, 0); + if ((packInfo.applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0) { + ComponentName svcName = new ComponentName(info.packageName, info.name); + if (DEBUG) { + Slog.i(TAG, "Binding to transport host " + svcName); + } + Intent intent = new Intent(transportServiceIntent); + intent.setComponent(svcName); + TransportConnection connection = new TransportConnection(); + mTransportConnections.add(connection); + context.bindServiceAsUser(intent, + connection, Context.BIND_AUTO_CREATE, + UserHandle.OWNER); + } else { + Slog.w(TAG, "Transport package not privileged: " + info.packageName); + } + } catch (Exception e) { + Slog.e(TAG, "Problem resolving transport service: " + e.getMessage()); + } } - } catch (PackageManager.NameNotFoundException nnf) { - // No such package? No binding. - if (DEBUG) Slog.v(TAG, "Google transport not present"); } // Now that we know about valid backup participants, parse any @@ -1298,13 +1313,16 @@ class BackupManagerService extends IBackupManager.Stub { // Add a transport to our set of available backends. If 'transport' is null, this // is an unregistration, and the transport's entry is removed from our bookkeeping. - private void registerTransport(String name, IBackupTransport transport) { + private void registerTransport(String name, String component, IBackupTransport transport) { synchronized (mTransports) { - if (DEBUG) Slog.v(TAG, "Registering transport " + name + " = " + transport); + if (DEBUG) Slog.v(TAG, "Registering transport " + + component + "::" + name + " = " + transport); if (transport != null) { mTransports.put(name, transport); + mTransportNames.put(component, name); } else { - mTransports.remove(name); + mTransports.remove(mTransportNames.get(component)); + mTransportNames.remove(component); // Nothing further to do in the unregistration case return; } @@ -1390,18 +1408,23 @@ class BackupManagerService extends IBackupManager.Stub { } }; - // ----- Track connection to GoogleBackupTransport service ----- - ServiceConnection mGoogleConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName name, IBinder service) { - if (DEBUG) Slog.v(TAG, "Connected to Google transport"); - mGoogleTransport = IBackupTransport.Stub.asInterface(service); - registerTransport(name.flattenToShortString(), mGoogleTransport); + // ----- Track connection to transports service ----- + class TransportConnection implements ServiceConnection { + @Override + public void onServiceConnected(ComponentName component, IBinder service) { + if (DEBUG) Slog.v(TAG, "Connected to transport " + component); + try { + IBackupTransport transport = IBackupTransport.Stub.asInterface(service); + registerTransport(transport.name(), component.flattenToShortString(), transport); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to register transport " + component); + } } - public void onServiceDisconnected(ComponentName name) { - if (DEBUG) Slog.v(TAG, "Disconnected from Google transport"); - mGoogleTransport = null; - registerTransport(name.flattenToShortString(), null); + @Override + public void onServiceDisconnected(ComponentName component) { + if (DEBUG) Slog.v(TAG, "Disconnected from transport " + component); + registerTransport(null, component.flattenToShortString(), null); } }; diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 594f683..baff661 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -3380,6 +3380,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { String pacFileUrl = ""; if (proxyProperties != null && (!TextUtils.isEmpty(proxyProperties.getHost()) || !TextUtils.isEmpty(proxyProperties.getPacFileUrl()))) { + if (!proxyProperties.isValid()) { + if (DBG) + log("Invalid proxy properties, ignoring: " + proxyProperties.toString()); + return; + } mGlobalProxy = new ProxyProperties(proxyProperties); host = mGlobalProxy.getHost(); port = mGlobalProxy.getPort(); @@ -3423,6 +3428,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { } else { proxyProperties = new ProxyProperties(host, port, exclList); } + if (!proxyProperties.isValid()) { + if (DBG) log("Invalid proxy properties, ignoring: " + proxyProperties.toString()); + return; + } + synchronized (mProxyLock) { mGlobalProxy = proxyProperties; } @@ -3447,6 +3457,10 @@ public class ConnectivityService extends IConnectivityManager.Stub { synchronized (mProxyLock) { if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return; if (mDefaultProxy == proxy) return; // catches repeated nulls + if (proxy != null && !proxy.isValid()) { + if (DBG) log("Invalid proxy properties, ignoring: " + proxy.toString()); + return; + } mDefaultProxy = proxy; if (mGlobalProxy != null) return; diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index 8cc80f7..2bb99d6 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -56,6 +56,7 @@ import android.content.pm.Signature; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; +import android.net.ProxyProperties; import android.net.Uri; import android.os.AsyncTask; import android.os.Binder; @@ -522,6 +523,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { || pm.getReceiverInfo(aa.info.getComponent(), 0, userHandle) == null) { removed = true; policy.mAdminList.remove(i); + policy.mAdminMap.remove(aa.info.getComponent()); } } catch (RemoteException re) { // Shouldn't happen @@ -2463,6 +2465,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } exclusionList = exclusionList.trim(); ContentResolver res = mContext.getContentResolver(); + + ProxyProperties proxyProperties = new ProxyProperties(data[0], proxyPort, exclusionList); + if (!proxyProperties.isValid()) { + Slog.e(TAG, "Invalid proxy properties, ignoring: " + proxyProperties.toString()); + return; + } Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, data[0]); Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, proxyPort); Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST, diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags index 8eaa91d..399e7d1 100644 --- a/services/java/com/android/server/EventLogTags.logtags +++ b/services/java/com/android/server/EventLogTags.logtags @@ -123,6 +123,18 @@ option java_package com.android.server # --------------------------- # Out of memory for surfaces. 31000 wm_no_surface_memory (Window|3),(PID|1|5),(Operation|3) +# Task created. +31001 wm_task_created (TaskId|1|5),(StackId|1|5) +# Task moved to top (1) or bottom (0). +31002 wm_task_moved (TaskId|1|5),(ToTop|1),(Index|1) +# Task removed with source explanation. +31003 wm_task_removed (TaskId|1|5),(Reason|3) +# Stack created. +31004 wm_stack_created (StackId|1|5),(RelativeBoxId|1|5),(Position|1),(Weight|1|6) +# Home stack moved to top (1) or bottom (0). +31005 wm_home_stack_moved (ToTop|1) +# Stack removed. +31006 wm_stack_removed (StackId|1|5) # --------------------------- diff --git a/services/java/com/android/server/LockSettingsService.java b/services/java/com/android/server/LockSettingsService.java index cd746cf..35e7afa 100644 --- a/services/java/com/android/server/LockSettingsService.java +++ b/services/java/com/android/server/LockSettingsService.java @@ -154,11 +154,11 @@ public class LockSettingsService extends ILockSettings.Stub { } private final void checkWritePermission(int userId) { - mContext.checkCallingOrSelfPermission(PERMISSION); + mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsWrite"); } private final void checkPasswordReadPermission(int userId) { - mContext.checkCallingOrSelfPermission(PERMISSION); + mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsRead"); } private final void checkReadPermission(String requestedKey, int userId) { diff --git a/services/java/com/android/server/NsdService.java b/services/java/com/android/server/NsdService.java index e0f415b..16d2468 100644 --- a/services/java/com/android/server/NsdService.java +++ b/services/java/com/android/server/NsdService.java @@ -483,10 +483,14 @@ public class NsdService extends INsdManager.Stub { clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4])); stopResolveService(id); - if (!getAddrInfo(id, cooked[3])) { + removeRequestMap(clientId, id, clientInfo); + + int id2 = getUniqueId(); + if (getAddrInfo(id2, cooked[3])) { + storeRequestMap(clientId, id2, clientInfo); + } else { clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, NsdManager.FAILURE_INTERNAL_ERROR, clientId); - removeRequestMap(clientId, id, clientInfo); clientInfo.mResolvedService = null; } break; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index bb14259..a42cbcf 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -55,6 +55,7 @@ import com.android.server.content.ContentService; import com.android.server.display.DisplayManagerService; import com.android.server.dreams.DreamManagerService; import com.android.server.input.InputManagerService; +import com.android.server.media.MediaRouterService; import com.android.server.net.NetworkPolicyManagerService; import com.android.server.net.NetworkStatsService; import com.android.server.os.SchedulingPolicyService; @@ -356,6 +357,7 @@ class ServerThread { DreamManagerService dreamy = null; AssetAtlasService atlas = null; PrintManagerService printManager = null; + MediaRouterService mediaRouter = null; // Bring up services needed for UI. if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { @@ -804,6 +806,16 @@ class ServerThread { } catch (Throwable e) { reportWtf("starting Print Service", e); } + + if (!disableNonCoreServices) { + try { + Slog.i(TAG, "Media Router Service"); + mediaRouter = new MediaRouterService(context); + ServiceManager.addService(Context.MEDIA_ROUTER_SERVICE, mediaRouter); + } catch (Throwable e) { + reportWtf("starting MediaRouterService", e); + } + } } // Before things start rolling, be sure we have decided whether @@ -916,6 +928,7 @@ class ServerThread { final InputManagerService inputManagerF = inputManager; final TelephonyRegistry telephonyRegistryF = telephonyRegistry; final PrintManagerService printManagerF = printManager; + final MediaRouterService mediaRouterF = mediaRouter; // We now tell the activity manager it is okay to run third party // code. It will call back into us once it has gotten to the state @@ -1063,6 +1076,12 @@ class ServerThread { } catch (Throwable e) { reportWtf("Notifying PrintManagerService running", e); } + + try { + if (mediaRouterF != null) mediaRouterF.systemRunning(); + } catch (Throwable e) { + reportWtf("Notifying MediaRouterService running", e); + } } }); diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java index c1a60ee..e6b6b93 100644 --- a/services/java/com/android/server/WallpaperManagerService.java +++ b/services/java/com/android/server/WallpaperManagerService.java @@ -40,6 +40,7 @@ import android.content.pm.ServiceInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.UserInfo; import android.content.res.Resources; +import android.graphics.Point; import android.os.Binder; import android.os.Bundle; import android.os.Environment; @@ -637,6 +638,14 @@ class WallpaperManagerService extends IWallpaperManager.Stub { return false; } + private Point getDefaultDisplaySize() { + Point p = new Point(); + WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); + Display d = wm.getDefaultDisplay(); + d.getRealSize(p); + return p; + } + public void setDimensionHints(int width, int height) throws RemoteException { checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS); synchronized (mLock) { @@ -648,10 +657,10 @@ class WallpaperManagerService extends IWallpaperManager.Stub { if (width <= 0 || height <= 0) { throw new IllegalArgumentException("width and height must be > 0"); } - // Make sure it is at least as large as the display's maximum size. - int maxSizeDimension = getMaximumSizeDimension(); - width = Math.max(width, maxSizeDimension); - height = Math.max(height, maxSizeDimension); + // Make sure it is at least as large as the display. + Point displaySize = getDefaultDisplaySize(); + width = Math.max(width, displaySize.x); + height = Math.max(height, displaySize.y); if (width != wallpaper.width || height != wallpaper.height) { wallpaper.width = width; diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/java/com/android/server/accounts/AccountManagerService.java index f972f70..aa9849e 100644 --- a/services/java/com/android/server/accounts/AccountManagerService.java +++ b/services/java/com/android/server/accounts/AccountManagerService.java @@ -190,10 +190,10 @@ public class AccountManagerService private final HashMap<String, Account[]> accountCache = new LinkedHashMap<String, Account[]>(); /** protected by the {@link #cacheLock} */ - private HashMap<Account, HashMap<String, String>> userDataCache = + private final HashMap<Account, HashMap<String, String>> userDataCache = new HashMap<Account, HashMap<String, String>>(); /** protected by the {@link #cacheLock} */ - private HashMap<Account, HashMap<String, String>> authTokenCache = + private final HashMap<Account, HashMap<String, String>> authTokenCache = new HashMap<Account, HashMap<String, String>>(); UserAccounts(Context context, int userId) { @@ -475,6 +475,7 @@ public class AccountManagerService validateAccountsInternal(getUserAccounts(userId), false /* invalidateAuthenticatorCache */); } + @Override public String getPassword(Account account) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "getPassword: " + account @@ -514,6 +515,7 @@ public class AccountManagerService } } + @Override public String getUserData(Account account, String key) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "getUserData: " + account @@ -533,6 +535,7 @@ public class AccountManagerService } } + @Override public AuthenticatorDescription[] getAuthenticatorTypes() { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "getAuthenticatorTypes: " @@ -763,6 +766,7 @@ public class AccountManagerService return db.insert(TABLE_EXTRAS, EXTRAS_KEY, values); } + @Override public void hasFeatures(IAccountManagerResponse response, Account account, String[] features) { if (Log.isLoggable(TAG, Log.VERBOSE)) { @@ -840,6 +844,7 @@ public class AccountManagerService } } + @Override public void removeAccount(IAccountManagerResponse response, Account account) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "removeAccount: " + account @@ -1049,6 +1054,7 @@ public class AccountManagerService } } + @Override public String peekAuthToken(Account account, String authTokenType) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "peekAuthToken: " + account @@ -1068,6 +1074,7 @@ public class AccountManagerService } } + @Override public void setAuthToken(Account account, String authTokenType, String authToken) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "setAuthToken: " + account @@ -1087,6 +1094,7 @@ public class AccountManagerService } } + @Override public void setPassword(Account account, String password) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "setAuthToken: " + account @@ -1135,6 +1143,7 @@ public class AccountManagerService mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId)); } + @Override public void clearPassword(Account account) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "clearPassword: " + account @@ -1152,6 +1161,7 @@ public class AccountManagerService } } + @Override public void setUserData(Account account, String key, String value) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "setUserData: " + account @@ -1225,6 +1235,7 @@ public class AccountManagerService } } + @Override public void getAuthTokenLabel(IAccountManagerResponse response, final String accountType, final String authTokenType) throws RemoteException { @@ -1271,6 +1282,7 @@ public class AccountManagerService } } + @Override public void getAuthToken(IAccountManagerResponse response, final Account account, final String authTokenType, final boolean notifyOnAuthFailure, final boolean expectActivityLaunch, Bundle loginOptionsIn) { @@ -1284,8 +1296,22 @@ public class AccountManagerService + ", pid " + Binder.getCallingPid()); } if (response == null) throw new IllegalArgumentException("response is null"); - if (account == null) throw new IllegalArgumentException("account is null"); - if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null"); + try { + if (account == null) { + Slog.w(TAG, "getAuthToken called with null account"); + response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, "account is null"); + return; + } + if (authTokenType == null) { + Slog.w(TAG, "getAuthToken called with null authTokenType"); + response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, "authTokenType is null"); + return; + } + } catch (RemoteException e) { + Slog.w(TAG, "Failed to report error back to the client." + e); + return; + } + checkBinderPermission(Manifest.permission.USE_CREDENTIALS); final UserAccounts accounts = getUserAccountsForCaller(); final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo; @@ -1294,11 +1320,6 @@ public class AccountManagerService final boolean customTokens = authenticatorInfo != null && authenticatorInfo.type.customTokens; - // Check to see that the app is authorized to access the account, in case it's a - // restricted account. - if (!ArrayUtils.contains(getAccounts((String) null), account)) { - throw new IllegalArgumentException("no such account"); - } // skip the check if customTokens final int callerUid = Binder.getCallingUid(); final boolean permissionGranted = customTokens || @@ -1472,6 +1493,7 @@ public class AccountManagerService return id; } + @Override public void addAccount(final IAccountManagerResponse response, final String accountType, final String authTokenType, final String[] requiredFeatures, final boolean expectActivityLaunch, final Bundle optionsIn) { @@ -1582,6 +1604,7 @@ public class AccountManagerService } } + @Override public void updateCredentials(IAccountManagerResponse response, final Account account, final String authTokenType, final boolean expectActivityLaunch, final Bundle loginOptions) { @@ -1620,6 +1643,7 @@ public class AccountManagerService } } + @Override public void editProperties(IAccountManagerResponse response, final String accountType, final boolean expectActivityLaunch) { if (Log.isLoggable(TAG, Log.VERBOSE)) { @@ -1657,7 +1681,7 @@ public class AccountManagerService private volatile Account[] mAccountsOfType = null; private volatile ArrayList<Account> mAccountsWithFeatures = null; private volatile int mCurrentAccount = 0; - private int mCallingUid; + private final int mCallingUid; public GetAccountsByTypeAndFeatureSession(UserAccounts accounts, IAccountManagerResponse response, String type, String[] features, int callingUid) { @@ -1941,6 +1965,7 @@ public class AccountManagerService return getAccountsAsUser(type, UserHandle.getCallingUserId(), packageName, packageUid); } + @Override public void getAccountsByFeatures(IAccountManagerResponse response, String type, String[] features) { if (Log.isLoggable(TAG, Log.VERBOSE)) { @@ -2069,6 +2094,7 @@ public class AccountManagerService unbind(); } + @Override public void binderDied() { mResponse = null; close(); @@ -2112,6 +2138,7 @@ public class AccountManagerService mMessageHandler.removeMessages(MESSAGE_TIMED_OUT, this); } + @Override public void onServiceConnected(ComponentName name, IBinder service) { mAuthenticator = IAccountAuthenticator.Stub.asInterface(service); try { @@ -2122,6 +2149,7 @@ public class AccountManagerService } } + @Override public void onServiceDisconnected(ComponentName name) { mAuthenticator = null; IAccountManagerResponse response = getResponseAndClose(); @@ -2217,7 +2245,14 @@ public class AccountManagerService Log.v(TAG, getClass().getSimpleName() + " calling onResult() on response " + response); } - response.onResult(result); + if ((result.getInt(AccountManager.KEY_ERROR_CODE, -1) > 0) && + (intent == null)) { + // All AccountManager error codes are greater than 0 + response.onError(result.getInt(AccountManager.KEY_ERROR_CODE), + result.getString(AccountManager.KEY_ERROR_MESSAGE)); + } else { + response.onResult(result); + } } } catch (RemoteException e) { // if the caller is dead then there is no one to care about remote exceptions @@ -2228,10 +2263,12 @@ public class AccountManagerService } } + @Override public void onRequestContinued() { mNumRequestContinued++; } + @Override public void onError(int errorCode, String errorMessage) { mNumErrors++; IAccountManagerResponse response = getResponseAndClose(); @@ -2731,6 +2768,7 @@ public class AccountManagerService return true; } + @Override public void updateAppPermission(Account account, String authTokenType, int uid, boolean value) throws RemoteException { final int callingUid = getCallingUid(); diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java index ea0b978a..933247e 100644 --- a/services/java/com/android/server/am/ActiveServices.java +++ b/services/java/com/android/server/am/ActiveServices.java @@ -307,7 +307,7 @@ public final class ActiveServices { ServiceRecord r = res.record; NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked( callingUid, r.packageName, service, service.getFlags(), null); - if (unscheduleServiceRestartLocked(r, callingUid)) { + if (unscheduleServiceRestartLocked(r, callingUid, false)) { if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r); } r.lastActivity = SystemClock.uptimeMillis(); @@ -701,7 +701,7 @@ public final class ActiveServices { final long origId = Binder.clearCallingIdentity(); try { - if (unscheduleServiceRestartLocked(s, callerApp.info.uid)) { + if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) { if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: " + s); } @@ -1002,14 +1002,11 @@ public final class ActiveServices { smap.mServicesByIntent.put(filter, r); // Make sure this component isn't in the pending list. - int N = mPendingServices.size(); - for (int i=0; i<N; i++) { + for (int i=mPendingServices.size()-1; i>=0; i--) { ServiceRecord pr = mPendingServices.get(i); if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid && pr.name.equals(name)) { mPendingServices.remove(i); - i--; - N--; } } } @@ -1101,6 +1098,14 @@ public final class ActiveServices { boolean allowCancel) { boolean canceled = false; + ServiceMap smap = getServiceMap(r.userId); + if (smap.mServicesByName.get(r.name) != r) { + ServiceRecord cur = smap.mServicesByName.get(r.name); + Slog.wtf(TAG, "Attempting to schedule restart of " + r + + " when found in map: " + cur); + return false; + } + final long now = SystemClock.uptimeMillis(); if ((r.serviceInfo.applicationInfo.flags @@ -1187,6 +1192,7 @@ public final class ActiveServices { if (!mRestartingServices.contains(r)) { r.createdFromFg = false; mRestartingServices.add(r); + r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(), now); } r.cancelNotification(); @@ -1209,8 +1215,9 @@ public final class ActiveServices { bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true); } - private final boolean unscheduleServiceRestartLocked(ServiceRecord r, int callingUid) { - if (r.restartDelay == 0) { + private final boolean unscheduleServiceRestartLocked(ServiceRecord r, int callingUid, + boolean force) { + if (!force && r.restartDelay == 0) { return false; } // Remove from the restarting list; if the service is currently on the @@ -1220,10 +1227,32 @@ public final class ActiveServices { if (removed || callingUid != r.appInfo.uid) { r.resetRestartCounter(); } + if (removed) { + clearRestartingIfNeededLocked(r); + } mAm.mHandler.removeCallbacks(r.restarter); return true; } + private void clearRestartingIfNeededLocked(ServiceRecord r) { + if (r.restartTracker != null) { + // If this is the last restarting record with this tracker, then clear + // the tracker's restarting state. + boolean stillTracking = false; + for (int i=mRestartingServices.size()-1; i>=0; i--) { + if (mRestartingServices.get(i).restartTracker == r.restartTracker) { + stillTracking = true; + break; + } + } + if (!stillTracking) { + r.restartTracker.setRestarting(false, mAm.mProcessStats.getMemFactorLocked(), + SystemClock.uptimeMillis()); + r.restartTracker = null; + } + } + } + private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting) { //Slog.i(TAG, "Bring up service:"); @@ -1243,7 +1272,9 @@ public final class ActiveServices { // We are now bringing the service up, so no longer in the // restarting state. - mRestartingServices.remove(r); + if (mRestartingServices.remove(r)) { + clearRestartingIfNeededLocked(r); + } // Make sure this service is no longer considered delayed, we are starting it now. if (r.delayed) { @@ -1383,6 +1414,7 @@ public final class ActiveServices { } finally { if (!created) { app.services.remove(r); + r.app = null; scheduleServiceRestartLocked(r, false); } } @@ -1553,16 +1585,13 @@ public final class ActiveServices { smap.mServicesByName.remove(r.name); smap.mServicesByIntent.remove(r.intent); r.totalRestartCount = 0; - unscheduleServiceRestartLocked(r, 0); + unscheduleServiceRestartLocked(r, 0, true); // Also make sure it is not on the pending list. - int N = mPendingServices.size(); - for (int i=0; i<N; i++) { + for (int i=mPendingServices.size()-1; i>=0; i--) { if (mPendingServices.get(i) == r) { mPendingServices.remove(i); if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r); - i--; - N--; } } @@ -1581,6 +1610,7 @@ public final class ActiveServices { } r.app.services.remove(r); if (r.app.thread != null) { + updateServiceForegroundLocked(r.app, false); try { bumpServiceExecutingLocked(r, false, "destroy"); mDestroyingServices.add(r); @@ -1591,7 +1621,6 @@ public final class ActiveServices { + r.shortName, e); serviceProcessGoneLocked(r); } - updateServiceForegroundLocked(r.app, false); } else { if (DEBUG_SERVICE) Slog.v( TAG, "Removed service that has no process: " + r); @@ -1769,6 +1798,7 @@ public final class ActiveServices { long now = SystemClock.uptimeMillis(); r.tracker.setExecuting(false, memFactor, now); r.tracker.setBound(false, memFactor, now); + r.tracker.setStarted(false, memFactor, now); } serviceDoneExecutingLocked(r, true, true); } @@ -1816,6 +1846,12 @@ public final class ActiveServices { r.tracker = null; } } + if (finishing) { + if (r.app != null) { + r.app.services.remove(r); + } + r.app = null; + } } } @@ -1894,6 +1930,7 @@ public final class ActiveServices { Slog.i(TAG, " Force stopping service " + service); if (service.app != null) { service.app.removed = true; + service.app.services.remove(service); } service.app = null; service.isolatedProc = null; @@ -1960,8 +1997,7 @@ public final class ActiveServices { } } - final void killServicesLocked(ProcessRecord app, - boolean allowRestart) { + final void killServicesLocked(ProcessRecord app, boolean allowRestart) { // Report disconnected services. if (false) { // XXX we are letting the client link to the service for @@ -1990,20 +2026,15 @@ public final class ActiveServices { } } - // Clean up any connections this application has to other services. - for (int i=app.connections.size()-1; i>=0; i--) { - ConnectionRecord r = app.connections.valueAt(i); - removeConnectionLocked(r, app, null); - } - app.connections.clear(); - + // First clear app state from services. for (int i=app.services.size()-1; i>=0; i--) { - // Any services running in the application need to be placed - // back in the pending list. ServiceRecord sr = app.services.valueAt(i); synchronized (sr.stats.getBatteryStats()) { sr.stats.stopLaunchedLocked(); } + if (sr.app != null) { + sr.app.services.remove(sr); + } sr.app = null; sr.isolatedProc = null; sr.executeNesting = 0; @@ -2020,8 +2051,33 @@ public final class ActiveServices { b.binder = null; b.requested = b.received = b.hasBound = false; } + } - if (sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags + // Clean up any connections this application has to other services. + for (int i=app.connections.size()-1; i>=0; i--) { + ConnectionRecord r = app.connections.valueAt(i); + removeConnectionLocked(r, app, null); + } + app.connections.clear(); + + ServiceMap smap = getServiceMap(app.userId); + + // Now do remaining service cleanup. + for (int i=app.services.size()-1; i>=0; i--) { + ServiceRecord sr = app.services.valueAt(i); + // Sanity check: if the service listed for the app is not one + // we actually are maintaining, drop it. + if (smap.mServicesByName.get(sr.name) != sr) { + ServiceRecord cur = smap.mServicesByName.get(sr.name); + Slog.wtf(TAG, "Service " + sr + " in process " + app + + " not same as in map: " + cur); + app.services.removeAt(i); + continue; + } + + // Any services running in the application may need to be placed + // back in the pending list. + if (allowRestart && sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags &ApplicationInfo.FLAG_PERSISTENT) == 0) { Slog.w(TAG, "Service crashed " + sr.crashCount + " times, stopping: " + sr); @@ -2054,6 +2110,23 @@ public final class ActiveServices { if (!allowRestart) { app.services.clear(); + + // Make sure there are no more restarting services for this process. + for (int i=mRestartingServices.size()-1; i>=0; i--) { + ServiceRecord r = mRestartingServices.get(i); + if (r.processName.equals(app.processName) && + r.serviceInfo.applicationInfo.uid == app.info.uid) { + mRestartingServices.remove(i); + clearRestartingIfNeededLocked(r); + } + } + for (int i=mPendingServices.size()-1; i>=0; i--) { + ServiceRecord r = mPendingServices.get(i); + if (r.processName.equals(app.processName) && + r.serviceInfo.applicationInfo.uid == app.info.uid) { + mPendingServices.remove(i); + } + } } // Make sure we have no more records on the stopping list. diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 164e7b7..9201b1d 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -2149,7 +2149,8 @@ public final class ActivityManagerService extends ActivityManagerNative totalUTime += otherUTime; totalSTime += otherSTime; if (pr != null) { - BatteryStatsImpl.Uid.Proc ps = pr.batteryStats; + BatteryStatsImpl.Uid.Proc ps = bstats.getProcessStatsLocked( + st.name, st.pid); ps.addCpuTimeLocked(st.rel_utime-otherUTime, st.rel_stime-otherSTime); ps.addSpeedStepTimes(cpuSpeedTimes); @@ -2769,10 +2770,10 @@ public final class ActivityManagerService extends ActivityManagerNative app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, null); - BatteryStatsImpl bs = app.batteryStats.getBatteryStats(); + BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics(); synchronized (bs) { if (bs.isOnBattery()) { - app.batteryStats.incStartsLocked(); + bs.getProcessStatsLocked(app.uid, app.processName).incStartsLocked(); } } @@ -8150,10 +8151,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } } - synchronized (stats) { - ps = stats.getProcessStatsLocked(info.uid, proc); - } - return new ProcessRecord(ps, info, proc, uid); + return new ProcessRecord(stats, info, proc, uid); } final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated) { @@ -11901,6 +11899,7 @@ public final class ActivityManagerService extends ActivityManagerNative boolean dumpDalvik = false; boolean oomOnly = false; boolean isCompact = false; + boolean localOnly = false; int opti = 0; while (opti < args.length) { @@ -11919,12 +11918,15 @@ public final class ActivityManagerService extends ActivityManagerNative isCompact = true; } else if ("--oom".equals(opt)) { oomOnly = true; + } else if ("--local".equals(opt)) { + localOnly = true; } else if ("-h".equals(opt)) { pw.println("meminfo dump options: [-a] [-d] [-c] [--oom] [process]"); pw.println(" -a: include all available information for each process."); pw.println(" -d: include dalvik details when dumping process details."); pw.println(" -c: dump in a compact machine-parseable representation."); pw.println(" --oom: only show processes organized by oom adj."); + pw.println(" --local: only collect details locally, don't call process."); pw.println("If [process] is specified it can be the name or "); pw.println("pid of a specific process to dump."); return; @@ -12041,14 +12043,22 @@ public final class ActivityManagerService extends ActivityManagerNative mi.dalvikPrivateDirty = (int)tmpLong[0]; } if (dumpDetails) { - try { - pw.flush(); - thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails, - dumpDalvik, innerArgs); - } catch (RemoteException e) { - if (!isCheckinRequest) { - pw.println("Got RemoteException!"); + if (localOnly) { + ActivityThread.dumpMemInfoTable(pw, mi, isCheckinRequest, dumpFullDetails, + dumpDalvik, pid, r.processName, 0, 0, 0, 0, 0, 0); + if (isCheckinRequest) { + pw.println(); + } + } else { + try { pw.flush(); + thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails, + dumpDalvik, innerArgs); + } catch (RemoteException e) { + if (!isCheckinRequest) { + pw.println("Got RemoteException!"); + pw.flush(); + } } } } diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 809452c..0e15261 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -36,7 +36,6 @@ import static com.android.server.am.ActivityStackSupervisor.DEBUG_SAVED_STATE; import static com.android.server.am.ActivityStackSupervisor.DEBUG_STATES; import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; -import android.os.Trace; import com.android.internal.os.BatteryStatsImpl; import com.android.internal.util.Objects; import com.android.server.Watchdog; @@ -64,12 +63,14 @@ import android.graphics.Bitmap; import android.net.Uri; import android.os.Binder; import android.os.Bundle; +import android.os.Debug; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.SystemClock; +import android.os.Trace; import android.os.UserHandle; import android.util.EventLog; import android.util.Slog; @@ -1143,7 +1144,7 @@ final class ActivityStack { } else if (isActivityOverHome(r)) { if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r); showHomeBehindStack = true; - behindFullscreen = true; + behindFullscreen = !isHomeStack(); } } else { if (DEBUG_VISBILITY) Slog.v( @@ -1716,7 +1717,7 @@ final class ActivityStack { mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen, (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, - r.userId); + r.userId, r.info.configChanges); if (VALIDATE_TOKENS) { validateAppTokensLocked(); } @@ -1777,7 +1778,8 @@ final class ActivityStack { r.updateOptionsLocked(options); mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen, - (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId); + (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId, + r.info.configChanges); boolean doShow = true; if (newTask) { // Even though this activity is starting fresh, we still need @@ -1820,7 +1822,8 @@ final class ActivityStack { // because there is nothing for it to animate on top of. mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen, - (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId); + (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId, + r.info.configChanges); ActivityOptions.abort(options); } if (VALIDATE_TOKENS) { @@ -1910,26 +1913,38 @@ final class ActivityStack { // bottom of the activity stack. This also keeps it // correctly ordered with any activities we previously // moved. + final ThumbnailHolder newThumbHolder; + final TaskRecord targetTask; final ActivityRecord bottom = !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ? - mTaskHistory.get(0).mActivities.get(0) : null; + mTaskHistory.get(0).mActivities.get(0) : null; if (bottom != null && target.taskAffinity != null && target.taskAffinity.equals(bottom.task.affinity)) { // If the activity currently at the bottom has the // same task affinity as the one we are moving, // then merge it into the same task. - target.setTask(bottom.task, bottom.thumbHolder, false); + targetTask = bottom.task; + newThumbHolder = bottom.thumbHolder == null ? targetTask : bottom.thumbHolder; if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target + " out to bottom task " + bottom.task); } else { - target.setTask(createTaskRecord(mStackSupervisor.getNextTaskId(), target.info, - null, false), null, false); - target.task.affinityIntent = target.intent; + targetTask = createTaskRecord(mStackSupervisor.getNextTaskId(), target.info, + null, false); + newThumbHolder = targetTask; + targetTask.affinityIntent = target.intent; if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target + " out to new task " + target.task); } - final TaskRecord targetTask = target.task; + if (clearWhenTaskReset) { + // This is the start of a new sub-task. + if (target.thumbHolder == null) { + target.thumbHolder = new ThumbnailHolder(); + } + } else { + target.thumbHolder = newThumbHolder; + } + final int targetTaskId = targetTask.taskId; mWindowManager.setAppGroupId(target.appToken, targetTaskId); @@ -1950,8 +1965,8 @@ final class ActivityStack { } } if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing activity " + p + " from task=" - + task + " adding to task=" + targetTask, - new RuntimeException("here").fillInStackTrace()); + + task + " adding to task=" + targetTask + + " Callers=" + Debug.getCallers(4)); if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p + " out to target's task " + target.task); p.setTask(targetTask, curThumbHolder, false); @@ -3145,7 +3160,9 @@ final class ActivityStack { final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null; if (task == tr && task.mOnTopOfHome || numTasks <= 1) { - task.mOnTopOfHome = false; + if (task != null) { + task.mOnTopOfHome = false; + } return mStackSupervisor.resumeHomeActivity(null); } diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java index 8251364..483b4a0 100644 --- a/services/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/java/com/android/server/am/ActivityStackSupervisor.java @@ -1386,17 +1386,22 @@ public final class ActivityStackSupervisor { launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; } + ActivityInfo newTaskInfo = null; + Intent newTaskIntent = null; final ActivityStack sourceStack; if (sourceRecord != null) { if (sourceRecord.finishing) { // If the source is finishing, we can't further count it as our source. This // is because the task it is associated with may now be empty and on its way out, // so we don't want to blindly throw it in to that task. Instead we will take - // the NEW_TASK flow and try to find a task for it. + // the NEW_TASK flow and try to find a task for it. But save the task information + // so it can be used when creating the new task. if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { Slog.w(TAG, "startActivity called from finishing " + sourceRecord + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent); launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; + newTaskInfo = sourceRecord.info; + newTaskIntent = sourceRecord.task.intent; } sourceRecord = null; sourceStack = null; @@ -1668,8 +1673,10 @@ public final class ActivityStackSupervisor { targetStack = adjustStackFocus(r); moveHomeStack(targetStack.isHomeStack()); if (reuseTask == null) { - r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true), - null, true); + r.setTask(targetStack.createTaskRecord(getNextTaskId(), + newTaskInfo != null ? newTaskInfo : r.info, + newTaskIntent != null ? newTaskIntent : intent, + true), null, true); if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " + r.task); } else { diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java index 0dd950e..2d59678 100644 --- a/services/java/com/android/server/am/BatteryStatsService.java +++ b/services/java/com/android/server/am/BatteryStatsService.java @@ -419,6 +419,20 @@ public final class BatteryStatsService extends IBatteryStats.Stub { } } + public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph); + } + } + + public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws); + } + } + public void noteWifiMulticastEnabledFromSource(WorkSource ws) { enforceCallingPermission(); synchronized (mStats) { diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java index dd3d8aa..bfb667f 100644 --- a/services/java/com/android/server/am/BroadcastQueue.java +++ b/services/java/com/android/server/am/BroadcastQueue.java @@ -27,6 +27,7 @@ import android.content.ComponentName; import android.content.IIntentReceiver; import android.content.Intent; import android.content.pm.ActivityInfo; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; @@ -814,6 +815,26 @@ public final class BroadcastQueue { + " to " + r.curApp + ": process crashing"); skip = true; } + if (!skip) { + boolean isAvailable = false; + try { + isAvailable = AppGlobals.getPackageManager().isPackageAvailable( + info.activityInfo.packageName, + UserHandle.getUserId(info.activityInfo.applicationInfo.uid)); + } catch (Exception e) { + // all such failures mean we skip this receiver + Slog.w(TAG, "Exception getting recipient info for " + + info.activityInfo.packageName, e); + } + if (!isAvailable) { + if (DEBUG_BROADCAST) { + Slog.v(TAG, "Skipping delivery to " + info.activityInfo.packageName + + " / " + info.activityInfo.applicationInfo.uid + + " : package no longer available"); + } + skip = true; + } + } if (skip) { if (DEBUG_BROADCAST) Slog.v(TAG, diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java index 576adc2..423e540 100644 --- a/services/java/com/android/server/am/ConnectionRecord.java +++ b/services/java/com/android/server/am/ConnectionRecord.java @@ -27,7 +27,7 @@ import java.io.PrintWriter; */ final class ConnectionRecord { final AppBindRecord binding; // The application/service binding. - final ActivityRecord activity; // If non-null, the owning activity. + final ActivityRecord activity; // If non-null, the owning activity. final IServiceConnection conn; // The client connection. final int flags; // Binding options. final int clientLabel; // String resource labeling this client. diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java index 187cd44..217a8d6 100644 --- a/services/java/com/android/server/am/ProcessRecord.java +++ b/services/java/com/android/server/am/ProcessRecord.java @@ -46,7 +46,7 @@ import java.util.ArrayList; * is currently running. */ final class ProcessRecord { - final BatteryStatsImpl.Uid.Proc batteryStats; // where to collect runtime statistics + private final BatteryStatsImpl mBatteryStats; // where to collect runtime statistics final ApplicationInfo info; // all about the first app in the process final boolean isolated; // true if this is a special isolated process final int uid; // uid of process; may be different from 'info' if isolated @@ -273,8 +273,8 @@ final class ProcessRecord { } if (!keeping) { long wtime; - synchronized (batteryStats.getBatteryStats()) { - wtime = batteryStats.getBatteryStats().getProcessWakeTime(info.uid, + synchronized (mBatteryStats) { + wtime = mBatteryStats.getProcessWakeTime(info.uid, pid, SystemClock.elapsedRealtime()); } long timeUsed = wtime - lastWakeTime; @@ -359,9 +359,9 @@ final class ProcessRecord { } } - ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, ApplicationInfo _info, + ProcessRecord(BatteryStatsImpl _batteryStats, ApplicationInfo _info, String _processName, int _uid) { - batteryStats = _batteryStats; + mBatteryStats = _batteryStats; info = _info; isolated = _info.uid != _uid; uid = _uid; diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/java/com/android/server/am/ProcessStatsService.java index 8d16880..e05fcda 100644 --- a/services/java/com/android/server/am/ProcessStatsService.java +++ b/services/java/com/android/server/am/ProcessStatsService.java @@ -750,23 +750,12 @@ public final class ProcessStatsService extends IProcessStats.Stub { return; } else { // Not an option, last argument must be a package name. - try { - IPackageManager pm = AppGlobals.getPackageManager(); - if (pm.getPackageUid(arg, UserHandle.getCallingUserId()) >= 0) { - reqPackage = arg; - // Include all details, since we know we are only going to - // be dumping a smaller set of data. In fact only the details - // container per-package data, so that are needed to be able - // to dump anything at all when filtering by package. - dumpDetails = true; - } - } catch (RemoteException e) { - } - if (reqPackage == null) { - pw.println("Unknown package: " + arg); - dumpHelp(pw); - return; - } + reqPackage = arg; + // Include all details, since we know we are only going to + // be dumping a smaller set of data. In fact only the details + // container per-package data, so that are needed to be able + // to dump anything at all when filtering by package. + dumpDetails = true; } } } @@ -816,13 +805,14 @@ public final class ProcessStatsService extends IProcessStats.Stub { } return; } else if (aggregateHours != 0) { + pw.print("AGGREGATED OVER LAST "); pw.print(aggregateHours); pw.println(" HOURS:"); dumpAggregatedStats(pw, aggregateHours, now, reqPackage, isCompact, dumpDetails, dumpFullDetails, dumpAll, activeOnly); return; } boolean sepNeeded = false; - if (!currentOnly || isCheckin) { + if (dumpAll || isCheckin) { mWriteLock.lock(); try { ArrayList<String> files = getCommittedFiles(0, false, !isCheckin); @@ -882,11 +872,11 @@ public final class ProcessStatsService extends IProcessStats.Stub { } } if (!isCheckin) { - if (dumpAll) { + if (!currentOnly) { if (sepNeeded) { pw.println(); - pw.println("AGGREGATED OVER LAST 24 HOURS:"); } + pw.println("AGGREGATED OVER LAST 24 HOURS:"); dumpAggregatedStats(pw, 24, now, reqPackage, isCompact, dumpDetails, dumpFullDetails, dumpAll, activeOnly); pw.println(); @@ -901,8 +891,8 @@ public final class ProcessStatsService extends IProcessStats.Stub { } else { if (sepNeeded) { pw.println(); - pw.println("CURRENT STATS:"); } + pw.println("CURRENT STATS:"); if (dumpDetails || dumpFullDetails) { mProcessStats.dumpLocked(pw, reqPackage, now, !dumpFullDetails, dumpAll, activeOnly); diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java index cc1172a..80e6e94 100644 --- a/services/java/com/android/server/am/ServiceRecord.java +++ b/services/java/com/android/server/am/ServiceRecord.java @@ -85,6 +85,7 @@ final class ServiceRecord extends Binder { ProcessRecord app; // where this service is running or null. ProcessRecord isolatedProc; // keep track of isolated process, if requested ProcessStats.ServiceState tracker; // tracking service execution, may be null + ProcessStats.ServiceState restartTracker; // tracking service restart boolean delayed; // are we waiting to start this service in the background? boolean isForeground; // is service currently in foreground mode? int foregroundId; // Notification ID of last foreground req. @@ -340,6 +341,19 @@ final class ServiceRecord extends Binder { } } + public void makeRestarting(int memFactor, long now) { + if (restartTracker == null) { + if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) { + restartTracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName, + serviceInfo.applicationInfo.uid, serviceInfo.processName, serviceInfo.name); + } + if (restartTracker == null) { + return; + } + } + restartTracker.setRestarting(true, memFactor, now); + } + public AppBindRecord retrieveAppBindingLocked(Intent intent, ProcessRecord app) { Intent.FilterComparison filter = new Intent.FilterComparison(intent); diff --git a/services/java/com/android/server/content/ContentService.java b/services/java/com/android/server/content/ContentService.java index cb35ef1..023bf2b 100644 --- a/services/java/com/android/server/content/ContentService.java +++ b/services/java/com/android/server/content/ContentService.java @@ -660,7 +660,7 @@ public final class ContentService extends IContentService.Stub { int userId = UserHandle.getCallingUserId(); long identityToken = clearCallingIdentity(); try { - return getSyncManager().getSyncStorageEngine().getCurrentSyncs(userId); + return getSyncManager().getSyncStorageEngine().getCurrentSyncsCopy(userId); } finally { restoreCallingIdentity(identityToken); } diff --git a/services/java/com/android/server/content/SyncStorageEngine.java b/services/java/com/android/server/content/SyncStorageEngine.java index 41ef229..5ebf9ea 100644 --- a/services/java/com/android/server/content/SyncStorageEngine.java +++ b/services/java/com/android/server/content/SyncStorageEngine.java @@ -1295,20 +1295,40 @@ public class SyncStorageEngine extends Handler { } /** - * Return a list of the currently active syncs. Note that the returned items are the - * real, live active sync objects, so be careful what you do with it. + * Return a list of the currently active syncs. Note that the returned + * items are the real, live active sync objects, so be careful what you do + * with it. */ - public List<SyncInfo> getCurrentSyncs(int userId) { + private List<SyncInfo> getCurrentSyncs(int userId) { synchronized (mAuthorities) { - ArrayList<SyncInfo> syncs = mCurrentSyncs.get(userId); - if (syncs == null) { - syncs = new ArrayList<SyncInfo>(); - mCurrentSyncs.put(userId, syncs); + return getCurrentSyncsLocked(userId); + } + } + + /** + * @return a copy of the current syncs data structure. Will not return + * null. + */ + public List<SyncInfo> getCurrentSyncsCopy(int userId) { + synchronized (mAuthorities) { + final List<SyncInfo> syncs = getCurrentSyncsLocked(userId); + final List<SyncInfo> syncsCopy = new ArrayList<SyncInfo>(); + for (SyncInfo sync : syncs) { + syncsCopy.add(new SyncInfo(sync)); } - return syncs; + return syncsCopy; } } + private List<SyncInfo> getCurrentSyncsLocked(int userId) { + ArrayList<SyncInfo> syncs = mCurrentSyncs.get(userId); + if (syncs == null) { + syncs = new ArrayList<SyncInfo>(); + mCurrentSyncs.put(userId, syncs); + } + return syncs; + } + /** * Return an array of the current sync status for all authorities. Note * that the objects inside the array are the real, live status objects, diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java index 249c8b0..02f26b3 100644 --- a/services/java/com/android/server/display/DisplayManagerService.java +++ b/services/java/com/android/server/display/DisplayManagerService.java @@ -466,6 +466,9 @@ public final class DisplayManagerService extends IDisplayManager.Stub { @Override // Binder call public void scanWifiDisplays() { + mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, + "Permission required to scan wifi displays"); + final long token = Binder.clearCallingIdentity(); try { synchronized (mSyncRoot) { @@ -483,13 +486,14 @@ public final class DisplayManagerService extends IDisplayManager.Stub { if (address == null) { throw new IllegalArgumentException("address must not be null"); } + mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, + "Permission required to connect to a wifi display"); - final boolean trusted = canCallerConfigureWifiDisplay(); final long token = Binder.clearCallingIdentity(); try { synchronized (mSyncRoot) { if (mWifiDisplayAdapter != null) { - mWifiDisplayAdapter.requestConnectLocked(address, trusted); + mWifiDisplayAdapter.requestConnectLocked(address); } } } finally { @@ -499,12 +503,8 @@ public final class DisplayManagerService extends IDisplayManager.Stub { @Override public void pauseWifiDisplay() { - if (mContext.checkCallingPermission( - android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY" - + "permission to pause a wifi display session."); - } + mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, + "Permission required to pause a wifi display session"); final long token = Binder.clearCallingIdentity(); try { @@ -520,12 +520,8 @@ public final class DisplayManagerService extends IDisplayManager.Stub { @Override public void resumeWifiDisplay() { - if (mContext.checkCallingPermission( - android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY" - + "permission to resume a wifi display session."); - } + mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, + "Permission required to resume a wifi display session"); final long token = Binder.clearCallingIdentity(); try { @@ -541,6 +537,11 @@ public final class DisplayManagerService extends IDisplayManager.Stub { @Override // Binder call public void disconnectWifiDisplay() { + // This request does not require special permissions. + // Any app can request disconnection from the currently active wifi display. + // This exception should no longer be needed once wifi display control moves + // to the media router service. + final long token = Binder.clearCallingIdentity(); try { synchronized (mSyncRoot) { @@ -558,10 +559,8 @@ public final class DisplayManagerService extends IDisplayManager.Stub { if (address == null) { throw new IllegalArgumentException("address must not be null"); } - if (!canCallerConfigureWifiDisplay()) { - throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to " - + "rename a wifi display."); - } + mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, + "Permission required to rename to a wifi display"); final long token = Binder.clearCallingIdentity(); try { @@ -580,10 +579,8 @@ public final class DisplayManagerService extends IDisplayManager.Stub { if (address == null) { throw new IllegalArgumentException("address must not be null"); } - if (!canCallerConfigureWifiDisplay()) { - throw new SecurityException("Requires CONFIGURE_WIFI_DISPLAY permission to " - + "forget a wifi display."); - } + mContext.enforceCallingOrSelfPermission(Manifest.permission.CONFIGURE_WIFI_DISPLAY, + "Permission required to forget to a wifi display"); final long token = Binder.clearCallingIdentity(); try { @@ -599,6 +596,9 @@ public final class DisplayManagerService extends IDisplayManager.Stub { @Override // Binder call public WifiDisplayStatus getWifiDisplayStatus() { + // This request does not require special permissions. + // Any app can get information about available wifi displays. + final long token = Binder.clearCallingIdentity(); try { synchronized (mSyncRoot) { @@ -612,11 +612,6 @@ public final class DisplayManagerService extends IDisplayManager.Stub { } } - private boolean canCallerConfigureWifiDisplay() { - return mContext.checkCallingPermission(android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) - == PackageManager.PERMISSION_GRANTED; - } - @Override // Binder call public int createVirtualDisplay(IBinder appToken, String packageName, String name, int width, int height, int densityDpi, Surface surface, int flags) { diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java index f7bbdf8..fdef039 100644 --- a/services/java/com/android/server/display/WifiDisplayAdapter.java +++ b/services/java/com/android/server/display/WifiDisplayAdapter.java @@ -172,19 +172,9 @@ final class WifiDisplayAdapter extends DisplayAdapter { }); } - public void requestConnectLocked(final String address, final boolean trusted) { + public void requestConnectLocked(final String address) { if (DEBUG) { - Slog.d(TAG, "requestConnectLocked: address=" + address + ", trusted=" + trusted); - } - - if (!trusted) { - synchronized (getSyncRoot()) { - if (!isRememberedDisplayLocked(address)) { - Slog.w(TAG, "Ignoring request by an untrusted client to connect to " - + "an unknown wifi display: " + address); - return; - } - } + Slog.d(TAG, "requestConnectLocked: address=" + address); } getHandler().post(new Runnable() { @@ -400,8 +390,6 @@ final class WifiDisplayAdapter extends DisplayAdapter { mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height, refreshRate, deviceFlags, address, surface); sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED); - - scheduleUpdateNotificationLocked(); } private void removeDisplayDeviceLocked() { @@ -409,8 +397,6 @@ final class WifiDisplayAdapter extends DisplayAdapter { mDisplayDevice.destroyLocked(); sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED); mDisplayDevice = null; - - scheduleUpdateNotificationLocked(); } } @@ -457,21 +443,24 @@ final class WifiDisplayAdapter extends DisplayAdapter { // Runs on the handler. private void handleUpdateNotification() { - final boolean isConnected; + final int state; + final WifiDisplay display; synchronized (getSyncRoot()) { if (!mPendingNotificationUpdate) { return; } mPendingNotificationUpdate = false; - isConnected = (mDisplayDevice != null); + state = mActiveDisplayState; + display = mActiveDisplay; } // Cancel the old notification if there is one. mNotificationManager.cancelAsUser(null, - R.string.wifi_display_notification_title, UserHandle.ALL); + R.string.wifi_display_notification_disconnect, UserHandle.ALL); - if (isConnected) { + if (state == WifiDisplayStatus.DISPLAY_STATE_CONNECTING + || state == WifiDisplayStatus.DISPLAY_STATE_CONNECTED) { Context context = getContext(); // Initialize pending intents for the notification outside of the lock because @@ -493,20 +482,38 @@ final class WifiDisplayAdapter extends DisplayAdapter { // Post the notification. Resources r = context.getResources(); - Notification notification = new Notification.Builder(context) - .setContentTitle(r.getString( - R.string.wifi_display_notification_title)) - .setContentText(r.getString( - R.string.wifi_display_notification_message)) - .setContentIntent(mSettingsPendingIntent) - .setSmallIcon(R.drawable.ic_notify_wifidisplay) - .setOngoing(true) - .addAction(android.R.drawable.ic_menu_close_clear_cancel, - r.getString(R.string.wifi_display_notification_disconnect), - mDisconnectPendingIntent) - .build(); + Notification notification; + if (state == WifiDisplayStatus.DISPLAY_STATE_CONNECTING) { + notification = new Notification.Builder(context) + .setContentTitle(r.getString( + R.string.wifi_display_notification_connecting_title)) + .setContentText(r.getString( + R.string.wifi_display_notification_connecting_message, + display.getFriendlyDisplayName())) + .setContentIntent(mSettingsPendingIntent) + .setSmallIcon(R.drawable.ic_notification_cast_connecting) + .setOngoing(true) + .addAction(android.R.drawable.ic_menu_close_clear_cancel, + r.getString(R.string.wifi_display_notification_disconnect), + mDisconnectPendingIntent) + .build(); + } else { + notification = new Notification.Builder(context) + .setContentTitle(r.getString( + R.string.wifi_display_notification_connected_title)) + .setContentText(r.getString( + R.string.wifi_display_notification_connected_message, + display.getFriendlyDisplayName())) + .setContentIntent(mSettingsPendingIntent) + .setSmallIcon(R.drawable.ic_notification_cast_on) + .setOngoing(true) + .addAction(android.R.drawable.ic_menu_close_clear_cancel, + r.getString(R.string.wifi_display_notification_disconnect), + mDisconnectPendingIntent) + .build(); + } mNotificationManager.notifyAsUser(null, - R.string.wifi_display_notification_title, + R.string.wifi_display_notification_disconnect, notification, UserHandle.ALL); } } @@ -578,6 +585,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING; mActiveDisplay = display; scheduleStatusChangedBroadcastLocked(); + scheduleUpdateNotificationLocked(); } } } @@ -590,6 +598,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; mActiveDisplay = null; scheduleStatusChangedBroadcastLocked(); + scheduleUpdateNotificationLocked(); } } } @@ -607,6 +616,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED; mActiveDisplay = display; scheduleStatusChangedBroadcastLocked(); + scheduleUpdateNotificationLocked(); } } } @@ -629,6 +639,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { mActiveDisplay = display; renameDisplayDeviceLocked(display.getFriendlyDisplayName()); scheduleStatusChangedBroadcastLocked(); + scheduleUpdateNotificationLocked(); } } } @@ -644,6 +655,7 @@ final class WifiDisplayAdapter extends DisplayAdapter { mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; mActiveDisplay = null; scheduleStatusChangedBroadcastLocked(); + scheduleUpdateNotificationLocked(); } } } diff --git a/services/java/com/android/server/display/WifiDisplayController.java b/services/java/com/android/server/display/WifiDisplayController.java index 9a4cfb7..b2939fe 100644 --- a/services/java/com/android/server/display/WifiDisplayController.java +++ b/services/java/com/android/server/display/WifiDisplayController.java @@ -76,7 +76,7 @@ final class WifiDisplayController implements DumpUtils.Dump { private static final int DEFAULT_CONTROL_PORT = 7236; private static final int MAX_THROUGHPUT = 50; private static final int CONNECTION_TIMEOUT_SECONDS = 60; - private static final int RTSP_TIMEOUT_SECONDS = 15; + private static final int RTSP_TIMEOUT_SECONDS = 30; private static final int RTSP_TIMEOUT_SECONDS_CERT_MODE = 120; private static final int DISCOVER_PEERS_MAX_RETRIES = 10; diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java index d749e6c..3145805 100644 --- a/services/java/com/android/server/input/InputManagerService.java +++ b/services/java/com/android/server/input/InputManagerService.java @@ -294,6 +294,7 @@ public class InputManagerService extends IInputManager.Stub IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addAction(Intent.ACTION_PACKAGE_CHANGED); + filter.addAction(Intent.ACTION_PACKAGE_REPLACED); filter.addDataScheme("package"); mContext.registerReceiver(new BroadcastReceiver() { @Override diff --git a/services/java/com/android/server/media/MediaRouterService.java b/services/java/com/android/server/media/MediaRouterService.java new file mode 100644 index 0000000..a31695b --- /dev/null +++ b/services/java/com/android/server/media/MediaRouterService.java @@ -0,0 +1,1423 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.media; + +import com.android.internal.util.Objects; +import com.android.server.Watchdog; + +import android.Manifest; +import android.app.ActivityManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.media.AudioSystem; +import android.media.IMediaRouterClient; +import android.media.IMediaRouterService; +import android.media.MediaRouter; +import android.media.MediaRouterClientState; +import android.media.RemoteDisplayState; +import android.media.RemoteDisplayState.RemoteDisplayInfo; +import android.os.Binder; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.RemoteException; +import android.os.SystemClock; +import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.Log; +import android.util.Slog; +import android.util.SparseArray; +import android.util.TimeUtils; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Provides a mechanism for discovering media routes and manages media playback + * behalf of applications. + * <p> + * Currently supports discovering remote displays via remote display provider + * services that have been registered by applications. + * </p> + */ +public final class MediaRouterService extends IMediaRouterService.Stub + implements Watchdog.Monitor { + private static final String TAG = "MediaRouterService"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + /** + * Timeout in milliseconds for a selected route to transition from a + * disconnected state to a connecting state. If we don't observe any + * progress within this interval, then we will give up and unselect the route. + */ + static final long CONNECTING_TIMEOUT = 5000; + + /** + * Timeout in milliseconds for a selected route to transition from a + * connecting state to a connected state. If we don't observe any + * progress within this interval, then we will give up and unselect the route. + */ + static final long CONNECTED_TIMEOUT = 60000; + + private final Context mContext; + + // State guarded by mLock. + private final Object mLock = new Object(); + private final SparseArray<UserRecord> mUserRecords = new SparseArray<UserRecord>(); + private final ArrayMap<IBinder, ClientRecord> mAllClientRecords = + new ArrayMap<IBinder, ClientRecord>(); + private int mCurrentUserId = -1; + + public MediaRouterService(Context context) { + mContext = context; + Watchdog.getInstance().addMonitor(this); + } + + public void systemRunning() { + IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED); + mContext.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(Intent.ACTION_USER_SWITCHED)) { + switchUser(); + } + } + }, filter); + + switchUser(); + } + + @Override + public void monitor() { + synchronized (mLock) { /* check for deadlock */ } + } + + // Binder call + @Override + public void registerClientAsUser(IMediaRouterClient client, String packageName, int userId) { + if (client == null) { + throw new IllegalArgumentException("client must not be null"); + } + + final int uid = Binder.getCallingUid(); + if (!validatePackageName(uid, packageName)) { + throw new SecurityException("packageName must match the calling uid"); + } + + final int pid = Binder.getCallingPid(); + final int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId, + false /*allowAll*/, true /*requireFull*/, "registerClientAsUser", packageName); + final boolean trusted = mContext.checkCallingOrSelfPermission( + android.Manifest.permission.CONFIGURE_WIFI_DISPLAY) == + PackageManager.PERMISSION_GRANTED; + final long token = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + registerClientLocked(client, pid, packageName, resolvedUserId, trusted); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + + // Binder call + @Override + public void unregisterClient(IMediaRouterClient client) { + if (client == null) { + throw new IllegalArgumentException("client must not be null"); + } + + final long token = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + unregisterClientLocked(client, false); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + + // Binder call + @Override + public MediaRouterClientState getState(IMediaRouterClient client) { + if (client == null) { + throw new IllegalArgumentException("client must not be null"); + } + + final long token = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + return getStateLocked(client); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + + // Binder call + @Override + public void setDiscoveryRequest(IMediaRouterClient client, + int routeTypes, boolean activeScan) { + if (client == null) { + throw new IllegalArgumentException("client must not be null"); + } + + final long token = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + setDiscoveryRequestLocked(client, routeTypes, activeScan); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + + // Binder call + // A null routeId means that the client wants to unselect its current route. + // The explicit flag indicates whether the change was explicitly requested by the + // user or the application which may cause changes to propagate out to the rest + // of the system. Should be false when the change is in response to a new globally + // selected route or a default selection. + @Override + public void setSelectedRoute(IMediaRouterClient client, String routeId, boolean explicit) { + if (client == null) { + throw new IllegalArgumentException("client must not be null"); + } + + final long token = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + setSelectedRouteLocked(client, routeId, explicit); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + + // Binder call + @Override + public void requestSetVolume(IMediaRouterClient client, String routeId, int volume) { + if (client == null) { + throw new IllegalArgumentException("client must not be null"); + } + if (routeId == null) { + throw new IllegalArgumentException("routeId must not be null"); + } + + final long token = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + requestSetVolumeLocked(client, routeId, volume); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + + // Binder call + @Override + public void requestUpdateVolume(IMediaRouterClient client, String routeId, int direction) { + if (client == null) { + throw new IllegalArgumentException("client must not be null"); + } + if (routeId == null) { + throw new IllegalArgumentException("routeId must not be null"); + } + + final long token = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + requestUpdateVolumeLocked(client, routeId, direction); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + + // Binder call + @Override + public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { + if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump MediaRouterService from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + pw.println("MEDIA ROUTER SERVICE (dumpsys media_router)"); + pw.println(); + pw.println("Global state"); + pw.println(" mCurrentUserId=" + mCurrentUserId); + + synchronized (mLock) { + final int count = mUserRecords.size(); + for (int i = 0; i < count; i++) { + UserRecord userRecord = mUserRecords.valueAt(i); + pw.println(); + userRecord.dump(pw, ""); + } + } + } + + void switchUser() { + synchronized (mLock) { + int userId = ActivityManager.getCurrentUser(); + if (mCurrentUserId != userId) { + final int oldUserId = mCurrentUserId; + mCurrentUserId = userId; // do this first + + UserRecord oldUser = mUserRecords.get(oldUserId); + if (oldUser != null) { + oldUser.mHandler.sendEmptyMessage(UserHandler.MSG_STOP); + disposeUserIfNeededLocked(oldUser); // since no longer current user + } + + UserRecord newUser = mUserRecords.get(userId); + if (newUser != null) { + newUser.mHandler.sendEmptyMessage(UserHandler.MSG_START); + } + } + } + } + + void clientDied(ClientRecord clientRecord) { + synchronized (mLock) { + unregisterClientLocked(clientRecord.mClient, true); + } + } + + private void registerClientLocked(IMediaRouterClient client, + int pid, String packageName, int userId, boolean trusted) { + final IBinder binder = client.asBinder(); + ClientRecord clientRecord = mAllClientRecords.get(binder); + if (clientRecord == null) { + boolean newUser = false; + UserRecord userRecord = mUserRecords.get(userId); + if (userRecord == null) { + userRecord = new UserRecord(userId); + newUser = true; + } + clientRecord = new ClientRecord(userRecord, client, pid, packageName, trusted); + try { + binder.linkToDeath(clientRecord, 0); + } catch (RemoteException ex) { + throw new RuntimeException("Media router client died prematurely.", ex); + } + + if (newUser) { + mUserRecords.put(userId, userRecord); + initializeUserLocked(userRecord); + } + + userRecord.mClientRecords.add(clientRecord); + mAllClientRecords.put(binder, clientRecord); + initializeClientLocked(clientRecord); + } + } + + private void unregisterClientLocked(IMediaRouterClient client, boolean died) { + ClientRecord clientRecord = mAllClientRecords.remove(client.asBinder()); + if (clientRecord != null) { + UserRecord userRecord = clientRecord.mUserRecord; + userRecord.mClientRecords.remove(clientRecord); + disposeClientLocked(clientRecord, died); + disposeUserIfNeededLocked(userRecord); // since client removed from user + } + } + + private MediaRouterClientState getStateLocked(IMediaRouterClient client) { + ClientRecord clientRecord = mAllClientRecords.get(client.asBinder()); + if (clientRecord != null) { + return clientRecord.getState(); + } + return null; + } + + private void setDiscoveryRequestLocked(IMediaRouterClient client, + int routeTypes, boolean activeScan) { + final IBinder binder = client.asBinder(); + ClientRecord clientRecord = mAllClientRecords.get(binder); + if (clientRecord != null) { + // Only let the system discover remote display routes for now. + if (!clientRecord.mTrusted) { + routeTypes &= ~MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY; + } + + if (clientRecord.mRouteTypes != routeTypes + || clientRecord.mActiveScan != activeScan) { + if (DEBUG) { + Slog.d(TAG, clientRecord + ": Set discovery request, routeTypes=0x" + + Integer.toHexString(routeTypes) + ", activeScan=" + activeScan); + } + clientRecord.mRouteTypes = routeTypes; + clientRecord.mActiveScan = activeScan; + clientRecord.mUserRecord.mHandler.sendEmptyMessage( + UserHandler.MSG_UPDATE_DISCOVERY_REQUEST); + } + } + } + + private void setSelectedRouteLocked(IMediaRouterClient client, + String routeId, boolean explicit) { + ClientRecord clientRecord = mAllClientRecords.get(client.asBinder()); + if (clientRecord != null) { + final String oldRouteId = clientRecord.mSelectedRouteId; + if (!Objects.equal(routeId, oldRouteId)) { + if (DEBUG) { + Slog.d(TAG, clientRecord + ": Set selected route, routeId=" + routeId + + ", oldRouteId=" + oldRouteId + + ", explicit=" + explicit); + } + + clientRecord.mSelectedRouteId = routeId; + if (explicit) { + // Any app can disconnect from the globally selected route. + if (oldRouteId != null) { + clientRecord.mUserRecord.mHandler.obtainMessage( + UserHandler.MSG_UNSELECT_ROUTE, oldRouteId).sendToTarget(); + } + // Only let the system connect to new global routes for now. + // A similar check exists in the display manager for wifi display. + if (routeId != null && clientRecord.mTrusted) { + clientRecord.mUserRecord.mHandler.obtainMessage( + UserHandler.MSG_SELECT_ROUTE, routeId).sendToTarget(); + } + } + } + } + } + + private void requestSetVolumeLocked(IMediaRouterClient client, + String routeId, int volume) { + final IBinder binder = client.asBinder(); + ClientRecord clientRecord = mAllClientRecords.get(binder); + if (clientRecord != null) { + clientRecord.mUserRecord.mHandler.obtainMessage( + UserHandler.MSG_REQUEST_SET_VOLUME, volume, 0, routeId).sendToTarget(); + } + } + + private void requestUpdateVolumeLocked(IMediaRouterClient client, + String routeId, int direction) { + final IBinder binder = client.asBinder(); + ClientRecord clientRecord = mAllClientRecords.get(binder); + if (clientRecord != null) { + clientRecord.mUserRecord.mHandler.obtainMessage( + UserHandler.MSG_REQUEST_UPDATE_VOLUME, direction, 0, routeId).sendToTarget(); + } + } + + private void initializeUserLocked(UserRecord userRecord) { + if (DEBUG) { + Slog.d(TAG, userRecord + ": Initialized"); + } + if (userRecord.mUserId == mCurrentUserId) { + userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_START); + } + } + + private void disposeUserIfNeededLocked(UserRecord userRecord) { + // If there are no records left and the user is no longer current then go ahead + // and purge the user record and all of its associated state. If the user is current + // then leave it alone since we might be connected to a route or want to query + // the same route information again soon. + if (userRecord.mUserId != mCurrentUserId + && userRecord.mClientRecords.isEmpty()) { + if (DEBUG) { + Slog.d(TAG, userRecord + ": Disposed"); + } + mUserRecords.remove(userRecord.mUserId); + // Note: User already stopped (by switchUser) so no need to send stop message here. + } + } + + private void initializeClientLocked(ClientRecord clientRecord) { + if (DEBUG) { + Slog.d(TAG, clientRecord + ": Registered"); + } + } + + private void disposeClientLocked(ClientRecord clientRecord, boolean died) { + if (DEBUG) { + if (died) { + Slog.d(TAG, clientRecord + ": Died!"); + } else { + Slog.d(TAG, clientRecord + ": Unregistered"); + } + } + if (clientRecord.mRouteTypes != 0 || clientRecord.mActiveScan) { + clientRecord.mUserRecord.mHandler.sendEmptyMessage( + UserHandler.MSG_UPDATE_DISCOVERY_REQUEST); + } + clientRecord.dispose(); + } + + private boolean validatePackageName(int uid, String packageName) { + if (packageName != null) { + String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); + if (packageNames != null) { + for (String n : packageNames) { + if (n.equals(packageName)) { + return true; + } + } + } + } + return false; + } + + /** + * Information about a particular client of the media router. + * The contents of this object is guarded by mLock. + */ + final class ClientRecord implements DeathRecipient { + public final UserRecord mUserRecord; + public final IMediaRouterClient mClient; + public final int mPid; + public final String mPackageName; + public final boolean mTrusted; + + public int mRouteTypes; + public boolean mActiveScan; + public String mSelectedRouteId; + + public ClientRecord(UserRecord userRecord, IMediaRouterClient client, + int pid, String packageName, boolean trusted) { + mUserRecord = userRecord; + mClient = client; + mPid = pid; + mPackageName = packageName; + mTrusted = trusted; + } + + public void dispose() { + mClient.asBinder().unlinkToDeath(this, 0); + } + + @Override + public void binderDied() { + clientDied(this); + } + + MediaRouterClientState getState() { + return mTrusted ? mUserRecord.mTrustedState : mUserRecord.mUntrustedState; + } + + public void dump(PrintWriter pw, String prefix) { + pw.println(prefix + this); + + final String indent = prefix + " "; + pw.println(indent + "mTrusted=" + mTrusted); + pw.println(indent + "mRouteTypes=0x" + Integer.toHexString(mRouteTypes)); + pw.println(indent + "mActiveScan=" + mActiveScan); + pw.println(indent + "mSelectedRouteId=" + mSelectedRouteId); + } + + @Override + public String toString() { + return "Client " + mPackageName + " (pid " + mPid + ")"; + } + } + + /** + * Information about a particular user. + * The contents of this object is guarded by mLock. + */ + final class UserRecord { + public final int mUserId; + public final ArrayList<ClientRecord> mClientRecords = new ArrayList<ClientRecord>(); + public final UserHandler mHandler; + public MediaRouterClientState mTrustedState; + public MediaRouterClientState mUntrustedState; + + public UserRecord(int userId) { + mUserId = userId; + mHandler = new UserHandler(MediaRouterService.this, this); + } + + public void dump(final PrintWriter pw, String prefix) { + pw.println(prefix + this); + + final String indent = prefix + " "; + final int clientCount = mClientRecords.size(); + if (clientCount != 0) { + for (int i = 0; i < clientCount; i++) { + mClientRecords.get(i).dump(pw, indent); + } + } else { + pw.println(indent + "<no clients>"); + } + + pw.println(indent + "State"); + pw.println(indent + "mTrustedState=" + mTrustedState); + pw.println(indent + "mUntrustedState=" + mUntrustedState); + + if (!mHandler.runWithScissors(new Runnable() { + @Override + public void run() { + mHandler.dump(pw, indent); + } + }, 1000)) { + pw.println(indent + "<could not dump handler state>"); + } + } + + @Override + public String toString() { + return "User " + mUserId; + } + } + + /** + * Media router handler + * <p> + * Since remote display providers are designed to be single-threaded by nature, + * this class encapsulates all of the associated functionality and exports state + * to the service as it evolves. + * </p><p> + * One important task of this class is to keep track of the current globally selected + * route id for certain routes that have global effects, such as remote displays. + * Global route selections override local selections made within apps. The change + * is propagated to all apps so that they are all in sync. Synchronization works + * both ways. Whenever the globally selected route is explicitly unselected by any + * app, then it becomes unselected globally and all apps are informed. + * </p><p> + * This class is currently hardcoded to work with remote display providers but + * it is intended to be eventually extended to support more general route providers + * similar to the support library media router. + * </p> + */ + static final class UserHandler extends Handler + implements RemoteDisplayProviderWatcher.Callback, + RemoteDisplayProviderProxy.Callback { + public static final int MSG_START = 1; + public static final int MSG_STOP = 2; + public static final int MSG_UPDATE_DISCOVERY_REQUEST = 3; + public static final int MSG_SELECT_ROUTE = 4; + public static final int MSG_UNSELECT_ROUTE = 5; + public static final int MSG_REQUEST_SET_VOLUME = 6; + public static final int MSG_REQUEST_UPDATE_VOLUME = 7; + private static final int MSG_UPDATE_CLIENT_STATE = 8; + private static final int MSG_CONNECTION_TIMED_OUT = 9; + + private static final int TIMEOUT_REASON_NOT_AVAILABLE = 1; + private static final int TIMEOUT_REASON_CONNECTION_LOST = 2; + private static final int TIMEOUT_REASON_WAITING_FOR_CONNECTING = 3; + private static final int TIMEOUT_REASON_WAITING_FOR_CONNECTED = 4; + + // The relative order of these constants is important and expresses progress + // through the process of connecting to a route. + private static final int PHASE_NOT_AVAILABLE = -1; + private static final int PHASE_NOT_CONNECTED = 0; + private static final int PHASE_CONNECTING = 1; + private static final int PHASE_CONNECTED = 2; + + private final MediaRouterService mService; + private final UserRecord mUserRecord; + private final RemoteDisplayProviderWatcher mWatcher; + private final ArrayList<ProviderRecord> mProviderRecords = + new ArrayList<ProviderRecord>(); + private final ArrayList<IMediaRouterClient> mTempClients = + new ArrayList<IMediaRouterClient>(); + + private boolean mRunning; + private int mDiscoveryMode = RemoteDisplayState.DISCOVERY_MODE_NONE; + private RouteRecord mGloballySelectedRouteRecord; + private int mConnectionPhase = PHASE_NOT_AVAILABLE; + private int mConnectionTimeoutReason; + private long mConnectionTimeoutStartTime; + private boolean mClientStateUpdateScheduled; + + public UserHandler(MediaRouterService service, UserRecord userRecord) { + super(Looper.getMainLooper(), null, true); + mService = service; + mUserRecord = userRecord; + mWatcher = new RemoteDisplayProviderWatcher(service.mContext, this, + this, mUserRecord.mUserId); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_START: { + start(); + break; + } + case MSG_STOP: { + stop(); + break; + } + case MSG_UPDATE_DISCOVERY_REQUEST: { + updateDiscoveryRequest(); + break; + } + case MSG_SELECT_ROUTE: { + selectRoute((String)msg.obj); + break; + } + case MSG_UNSELECT_ROUTE: { + unselectRoute((String)msg.obj); + break; + } + case MSG_REQUEST_SET_VOLUME: { + requestSetVolume((String)msg.obj, msg.arg1); + break; + } + case MSG_REQUEST_UPDATE_VOLUME: { + requestUpdateVolume((String)msg.obj, msg.arg1); + break; + } + case MSG_UPDATE_CLIENT_STATE: { + updateClientState(); + break; + } + case MSG_CONNECTION_TIMED_OUT: { + connectionTimedOut(); + break; + } + } + } + + public void dump(PrintWriter pw, String prefix) { + pw.println(prefix + "Handler"); + + final String indent = prefix + " "; + pw.println(indent + "mRunning=" + mRunning); + pw.println(indent + "mDiscoveryMode=" + mDiscoveryMode); + pw.println(indent + "mGloballySelectedRouteRecord=" + mGloballySelectedRouteRecord); + pw.println(indent + "mConnectionPhase=" + mConnectionPhase); + pw.println(indent + "mConnectionTimeoutReason=" + mConnectionTimeoutReason); + pw.println(indent + "mConnectionTimeoutStartTime=" + (mConnectionTimeoutReason != 0 ? + TimeUtils.formatUptime(mConnectionTimeoutStartTime) : "<n/a>")); + + mWatcher.dump(pw, prefix); + + final int providerCount = mProviderRecords.size(); + if (providerCount != 0) { + for (int i = 0; i < providerCount; i++) { + mProviderRecords.get(i).dump(pw, prefix); + } + } else { + pw.println(indent + "<no providers>"); + } + } + + private void start() { + if (!mRunning) { + mRunning = true; + mWatcher.start(); // also starts all providers + } + } + + private void stop() { + if (mRunning) { + mRunning = false; + unselectGloballySelectedRoute(); + mWatcher.stop(); // also stops all providers + } + } + + private void updateDiscoveryRequest() { + int routeTypes = 0; + boolean activeScan = false; + synchronized (mService.mLock) { + final int count = mUserRecord.mClientRecords.size(); + for (int i = 0; i < count; i++) { + ClientRecord clientRecord = mUserRecord.mClientRecords.get(i); + routeTypes |= clientRecord.mRouteTypes; + activeScan |= clientRecord.mActiveScan; + } + } + + final int newDiscoveryMode; + if ((routeTypes & MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY) != 0) { + if (activeScan) { + newDiscoveryMode = RemoteDisplayState.DISCOVERY_MODE_ACTIVE; + } else { + newDiscoveryMode = RemoteDisplayState.DISCOVERY_MODE_PASSIVE; + } + } else { + newDiscoveryMode = RemoteDisplayState.DISCOVERY_MODE_NONE; + } + + if (mDiscoveryMode != newDiscoveryMode) { + mDiscoveryMode = newDiscoveryMode; + final int count = mProviderRecords.size(); + for (int i = 0; i < count; i++) { + mProviderRecords.get(i).getProvider().setDiscoveryMode(mDiscoveryMode); + } + } + } + + private void selectRoute(String routeId) { + if (routeId != null + && (mGloballySelectedRouteRecord == null + || !routeId.equals(mGloballySelectedRouteRecord.getUniqueId()))) { + RouteRecord routeRecord = findRouteRecord(routeId); + if (routeRecord != null) { + unselectGloballySelectedRoute(); + + Slog.i(TAG, "Selected global route:" + routeRecord); + mGloballySelectedRouteRecord = routeRecord; + checkGloballySelectedRouteState(); + routeRecord.getProvider().setSelectedDisplay(routeRecord.getDescriptorId()); + + scheduleUpdateClientState(); + } + } + } + + private void unselectRoute(String routeId) { + if (routeId != null + && mGloballySelectedRouteRecord != null + && routeId.equals(mGloballySelectedRouteRecord.getUniqueId())) { + unselectGloballySelectedRoute(); + } + } + + private void unselectGloballySelectedRoute() { + if (mGloballySelectedRouteRecord != null) { + Slog.i(TAG, "Unselected global route:" + mGloballySelectedRouteRecord); + mGloballySelectedRouteRecord.getProvider().setSelectedDisplay(null); + mGloballySelectedRouteRecord = null; + checkGloballySelectedRouteState(); + + scheduleUpdateClientState(); + } + } + + private void requestSetVolume(String routeId, int volume) { + if (mGloballySelectedRouteRecord != null + && routeId.equals(mGloballySelectedRouteRecord.getUniqueId())) { + mGloballySelectedRouteRecord.getProvider().setDisplayVolume(volume); + } + } + + private void requestUpdateVolume(String routeId, int direction) { + if (mGloballySelectedRouteRecord != null + && routeId.equals(mGloballySelectedRouteRecord.getUniqueId())) { + mGloballySelectedRouteRecord.getProvider().adjustDisplayVolume(direction); + } + } + + @Override + public void addProvider(RemoteDisplayProviderProxy provider) { + provider.setCallback(this); + provider.setDiscoveryMode(mDiscoveryMode); + provider.setSelectedDisplay(null); // just to be safe + + ProviderRecord providerRecord = new ProviderRecord(provider); + mProviderRecords.add(providerRecord); + providerRecord.updateDescriptor(provider.getDisplayState()); + + scheduleUpdateClientState(); + } + + @Override + public void removeProvider(RemoteDisplayProviderProxy provider) { + int index = findProviderRecord(provider); + if (index >= 0) { + ProviderRecord providerRecord = mProviderRecords.remove(index); + providerRecord.updateDescriptor(null); // mark routes invalid + provider.setCallback(null); + provider.setDiscoveryMode(RemoteDisplayState.DISCOVERY_MODE_NONE); + + checkGloballySelectedRouteState(); + scheduleUpdateClientState(); + } + } + + @Override + public void onDisplayStateChanged(RemoteDisplayProviderProxy provider, + RemoteDisplayState state) { + updateProvider(provider, state); + } + + private void updateProvider(RemoteDisplayProviderProxy provider, + RemoteDisplayState state) { + int index = findProviderRecord(provider); + if (index >= 0) { + ProviderRecord providerRecord = mProviderRecords.get(index); + if (providerRecord.updateDescriptor(state)) { + checkGloballySelectedRouteState(); + scheduleUpdateClientState(); + } + } + } + + /** + * This function is called whenever the state of the globally selected route + * may have changed. It checks the state and updates timeouts or unselects + * the route as appropriate. + */ + private void checkGloballySelectedRouteState() { + // Unschedule timeouts when the route is unselected. + if (mGloballySelectedRouteRecord == null) { + mConnectionPhase = PHASE_NOT_AVAILABLE; + updateConnectionTimeout(0); + return; + } + + // Ensure that the route is still present and enabled. + if (!mGloballySelectedRouteRecord.isValid() + || !mGloballySelectedRouteRecord.isEnabled()) { + updateConnectionTimeout(TIMEOUT_REASON_NOT_AVAILABLE); + return; + } + + // Make sure we haven't lost our connection. + final int oldPhase = mConnectionPhase; + mConnectionPhase = getConnectionPhase(mGloballySelectedRouteRecord.getStatus()); + if (oldPhase >= PHASE_CONNECTING && mConnectionPhase < PHASE_CONNECTING) { + updateConnectionTimeout(TIMEOUT_REASON_CONNECTION_LOST); + return; + } + + // Check the route status. + switch (mConnectionPhase) { + case PHASE_CONNECTED: + if (oldPhase != PHASE_CONNECTED) { + Slog.i(TAG, "Connected to global route: " + + mGloballySelectedRouteRecord); + } + updateConnectionTimeout(0); + break; + case PHASE_CONNECTING: + if (oldPhase != PHASE_CONNECTING) { + Slog.i(TAG, "Connecting to global route: " + + mGloballySelectedRouteRecord); + } + updateConnectionTimeout(TIMEOUT_REASON_WAITING_FOR_CONNECTED); + break; + case PHASE_NOT_CONNECTED: + updateConnectionTimeout(TIMEOUT_REASON_WAITING_FOR_CONNECTING); + break; + case PHASE_NOT_AVAILABLE: + default: + updateConnectionTimeout(TIMEOUT_REASON_NOT_AVAILABLE); + break; + } + } + + private void updateConnectionTimeout(int reason) { + if (reason != mConnectionTimeoutReason) { + if (mConnectionTimeoutReason != 0) { + removeMessages(MSG_CONNECTION_TIMED_OUT); + } + mConnectionTimeoutReason = reason; + mConnectionTimeoutStartTime = SystemClock.uptimeMillis(); + switch (reason) { + case TIMEOUT_REASON_NOT_AVAILABLE: + case TIMEOUT_REASON_CONNECTION_LOST: + // Route became unavailable or connection lost. + // Unselect it immediately. + sendEmptyMessage(MSG_CONNECTION_TIMED_OUT); + break; + case TIMEOUT_REASON_WAITING_FOR_CONNECTING: + // Waiting for route to start connecting. + sendEmptyMessageDelayed(MSG_CONNECTION_TIMED_OUT, CONNECTING_TIMEOUT); + break; + case TIMEOUT_REASON_WAITING_FOR_CONNECTED: + // Waiting for route to complete connection. + sendEmptyMessageDelayed(MSG_CONNECTION_TIMED_OUT, CONNECTED_TIMEOUT); + break; + } + } + } + + private void connectionTimedOut() { + if (mConnectionTimeoutReason == 0 || mGloballySelectedRouteRecord == null) { + // Shouldn't get here. There must be a bug somewhere. + Log.wtf(TAG, "Handled connection timeout for no reason."); + return; + } + + switch (mConnectionTimeoutReason) { + case TIMEOUT_REASON_NOT_AVAILABLE: + Slog.i(TAG, "Global route no longer available: " + + mGloballySelectedRouteRecord); + break; + case TIMEOUT_REASON_CONNECTION_LOST: + Slog.i(TAG, "Global route connection lost: " + + mGloballySelectedRouteRecord); + break; + case TIMEOUT_REASON_WAITING_FOR_CONNECTING: + Slog.i(TAG, "Global route timed out while waiting for " + + "connection attempt to begin after " + + (SystemClock.uptimeMillis() - mConnectionTimeoutStartTime) + + " ms: " + mGloballySelectedRouteRecord); + break; + case TIMEOUT_REASON_WAITING_FOR_CONNECTED: + Slog.i(TAG, "Global route timed out while connecting after " + + (SystemClock.uptimeMillis() - mConnectionTimeoutStartTime) + + " ms: " + mGloballySelectedRouteRecord); + break; + } + mConnectionTimeoutReason = 0; + + unselectGloballySelectedRoute(); + } + + private void scheduleUpdateClientState() { + if (!mClientStateUpdateScheduled) { + mClientStateUpdateScheduled = true; + sendEmptyMessage(MSG_UPDATE_CLIENT_STATE); + } + } + + private void updateClientState() { + mClientStateUpdateScheduled = false; + + final String globallySelectedRouteId = mGloballySelectedRouteRecord != null ? + mGloballySelectedRouteRecord.getUniqueId() : null; + + // Build a new client state for trusted clients. + MediaRouterClientState trustedState = new MediaRouterClientState(); + trustedState.globallySelectedRouteId = globallySelectedRouteId; + final int providerCount = mProviderRecords.size(); + for (int i = 0; i < providerCount; i++) { + mProviderRecords.get(i).appendClientState(trustedState); + } + + // Build a new client state for untrusted clients that can only see + // the currently selected route. + MediaRouterClientState untrustedState = new MediaRouterClientState(); + untrustedState.globallySelectedRouteId = globallySelectedRouteId; + if (globallySelectedRouteId != null) { + untrustedState.routes.add(trustedState.getRoute(globallySelectedRouteId)); + } + + try { + synchronized (mService.mLock) { + // Update the UserRecord. + mUserRecord.mTrustedState = trustedState; + mUserRecord.mUntrustedState = untrustedState; + + // Collect all clients. + final int count = mUserRecord.mClientRecords.size(); + for (int i = 0; i < count; i++) { + mTempClients.add(mUserRecord.mClientRecords.get(i).mClient); + } + } + + // Notify all clients (outside of the lock). + final int count = mTempClients.size(); + for (int i = 0; i < count; i++) { + try { + mTempClients.get(i).onStateChanged(); + } catch (RemoteException ex) { + // ignore errors, client probably died + } + } + } finally { + // Clear the list in preparation for the next time. + mTempClients.clear(); + } + } + + private int findProviderRecord(RemoteDisplayProviderProxy provider) { + final int count = mProviderRecords.size(); + for (int i = 0; i < count; i++) { + ProviderRecord record = mProviderRecords.get(i); + if (record.getProvider() == provider) { + return i; + } + } + return -1; + } + + private RouteRecord findRouteRecord(String uniqueId) { + final int count = mProviderRecords.size(); + for (int i = 0; i < count; i++) { + RouteRecord record = mProviderRecords.get(i).findRouteByUniqueId(uniqueId); + if (record != null) { + return record; + } + } + return null; + } + + private static int getConnectionPhase(int status) { + switch (status) { + case MediaRouter.RouteInfo.STATUS_NONE: + case MediaRouter.RouteInfo.STATUS_CONNECTED: + return PHASE_CONNECTED; + case MediaRouter.RouteInfo.STATUS_CONNECTING: + return PHASE_CONNECTING; + case MediaRouter.RouteInfo.STATUS_SCANNING: + case MediaRouter.RouteInfo.STATUS_AVAILABLE: + return PHASE_NOT_CONNECTED; + case MediaRouter.RouteInfo.STATUS_NOT_AVAILABLE: + case MediaRouter.RouteInfo.STATUS_IN_USE: + default: + return PHASE_NOT_AVAILABLE; + } + } + + static final class ProviderRecord { + private final RemoteDisplayProviderProxy mProvider; + private final String mUniquePrefix; + private final ArrayList<RouteRecord> mRoutes = new ArrayList<RouteRecord>(); + private RemoteDisplayState mDescriptor; + + public ProviderRecord(RemoteDisplayProviderProxy provider) { + mProvider = provider; + mUniquePrefix = provider.getFlattenedComponentName() + ":"; + } + + public RemoteDisplayProviderProxy getProvider() { + return mProvider; + } + + public String getUniquePrefix() { + return mUniquePrefix; + } + + public boolean updateDescriptor(RemoteDisplayState descriptor) { + boolean changed = false; + if (mDescriptor != descriptor) { + mDescriptor = descriptor; + + // Update all existing routes and reorder them to match + // the order of their descriptors. + int targetIndex = 0; + if (descriptor != null) { + if (descriptor.isValid()) { + final List<RemoteDisplayInfo> routeDescriptors = descriptor.displays; + final int routeCount = routeDescriptors.size(); + for (int i = 0; i < routeCount; i++) { + final RemoteDisplayInfo routeDescriptor = + routeDescriptors.get(i); + final String descriptorId = routeDescriptor.id; + final int sourceIndex = findRouteByDescriptorId(descriptorId); + if (sourceIndex < 0) { + // Add the route to the provider. + String uniqueId = assignRouteUniqueId(descriptorId); + RouteRecord route = + new RouteRecord(this, descriptorId, uniqueId); + mRoutes.add(targetIndex++, route); + route.updateDescriptor(routeDescriptor); + changed = true; + } else if (sourceIndex < targetIndex) { + // Ignore route with duplicate id. + Slog.w(TAG, "Ignoring route descriptor with duplicate id: " + + routeDescriptor); + } else { + // Reorder existing route within the list. + RouteRecord route = mRoutes.get(sourceIndex); + Collections.swap(mRoutes, sourceIndex, targetIndex++); + changed |= route.updateDescriptor(routeDescriptor); + } + } + } else { + Slog.w(TAG, "Ignoring invalid descriptor from media route provider: " + + mProvider.getFlattenedComponentName()); + } + } + + // Dispose all remaining routes that do not have matching descriptors. + for (int i = mRoutes.size() - 1; i >= targetIndex; i--) { + RouteRecord route = mRoutes.remove(i); + route.updateDescriptor(null); // mark route invalid + changed = true; + } + } + return changed; + } + + public void appendClientState(MediaRouterClientState state) { + final int routeCount = mRoutes.size(); + for (int i = 0; i < routeCount; i++) { + state.routes.add(mRoutes.get(i).getInfo()); + } + } + + public RouteRecord findRouteByUniqueId(String uniqueId) { + final int routeCount = mRoutes.size(); + for (int i = 0; i < routeCount; i++) { + RouteRecord route = mRoutes.get(i); + if (route.getUniqueId().equals(uniqueId)) { + return route; + } + } + return null; + } + + private int findRouteByDescriptorId(String descriptorId) { + final int routeCount = mRoutes.size(); + for (int i = 0; i < routeCount; i++) { + RouteRecord route = mRoutes.get(i); + if (route.getDescriptorId().equals(descriptorId)) { + return i; + } + } + return -1; + } + + public void dump(PrintWriter pw, String prefix) { + pw.println(prefix + this); + + final String indent = prefix + " "; + mProvider.dump(pw, indent); + + final int routeCount = mRoutes.size(); + if (routeCount != 0) { + for (int i = 0; i < routeCount; i++) { + mRoutes.get(i).dump(pw, indent); + } + } else { + pw.println(indent + "<no routes>"); + } + } + + @Override + public String toString() { + return "Provider " + mProvider.getFlattenedComponentName(); + } + + private String assignRouteUniqueId(String descriptorId) { + return mUniquePrefix + descriptorId; + } + } + + static final class RouteRecord { + private final ProviderRecord mProviderRecord; + private final String mDescriptorId; + private final MediaRouterClientState.RouteInfo mMutableInfo; + private MediaRouterClientState.RouteInfo mImmutableInfo; + private RemoteDisplayInfo mDescriptor; + + public RouteRecord(ProviderRecord providerRecord, + String descriptorId, String uniqueId) { + mProviderRecord = providerRecord; + mDescriptorId = descriptorId; + mMutableInfo = new MediaRouterClientState.RouteInfo(uniqueId); + } + + public RemoteDisplayProviderProxy getProvider() { + return mProviderRecord.getProvider(); + } + + public ProviderRecord getProviderRecord() { + return mProviderRecord; + } + + public String getDescriptorId() { + return mDescriptorId; + } + + public String getUniqueId() { + return mMutableInfo.id; + } + + public MediaRouterClientState.RouteInfo getInfo() { + if (mImmutableInfo == null) { + mImmutableInfo = new MediaRouterClientState.RouteInfo(mMutableInfo); + } + return mImmutableInfo; + } + + public boolean isValid() { + return mDescriptor != null; + } + + public boolean isEnabled() { + return mMutableInfo.enabled; + } + + public int getStatus() { + return mMutableInfo.statusCode; + } + + public boolean updateDescriptor(RemoteDisplayInfo descriptor) { + boolean changed = false; + if (mDescriptor != descriptor) { + mDescriptor = descriptor; + if (descriptor != null) { + final String name = computeName(descriptor); + if (!Objects.equal(mMutableInfo.name, name)) { + mMutableInfo.name = name; + changed = true; + } + final String description = computeDescription(descriptor); + if (!Objects.equal(mMutableInfo.description, description)) { + mMutableInfo.description = description; + changed = true; + } + final int supportedTypes = computeSupportedTypes(descriptor); + if (mMutableInfo.supportedTypes != supportedTypes) { + mMutableInfo.supportedTypes = supportedTypes; + changed = true; + } + final boolean enabled = computeEnabled(descriptor); + if (mMutableInfo.enabled != enabled) { + mMutableInfo.enabled = enabled; + changed = true; + } + final int statusCode = computeStatusCode(descriptor); + if (mMutableInfo.statusCode != statusCode) { + mMutableInfo.statusCode = statusCode; + changed = true; + } + final int playbackType = computePlaybackType(descriptor); + if (mMutableInfo.playbackType != playbackType) { + mMutableInfo.playbackType = playbackType; + changed = true; + } + final int playbackStream = computePlaybackStream(descriptor); + if (mMutableInfo.playbackStream != playbackStream) { + mMutableInfo.playbackStream = playbackStream; + changed = true; + } + final int volume = computeVolume(descriptor); + if (mMutableInfo.volume != volume) { + mMutableInfo.volume = volume; + changed = true; + } + final int volumeMax = computeVolumeMax(descriptor); + if (mMutableInfo.volumeMax != volumeMax) { + mMutableInfo.volumeMax = volumeMax; + changed = true; + } + final int volumeHandling = computeVolumeHandling(descriptor); + if (mMutableInfo.volumeHandling != volumeHandling) { + mMutableInfo.volumeHandling = volumeHandling; + changed = true; + } + final int presentationDisplayId = computePresentationDisplayId(descriptor); + if (mMutableInfo.presentationDisplayId != presentationDisplayId) { + mMutableInfo.presentationDisplayId = presentationDisplayId; + changed = true; + } + } + } + if (changed) { + mImmutableInfo = null; + } + return changed; + } + + public void dump(PrintWriter pw, String prefix) { + pw.println(prefix + this); + + final String indent = prefix + " "; + pw.println(indent + "mMutableInfo=" + mMutableInfo); + pw.println(indent + "mDescriptorId=" + mDescriptorId); + pw.println(indent + "mDescriptor=" + mDescriptor); + } + + @Override + public String toString() { + return "Route " + mMutableInfo.name + " (" + mMutableInfo.id + ")"; + } + + private static String computeName(RemoteDisplayInfo descriptor) { + // Note that isValid() already ensures the name is non-empty. + return descriptor.name; + } + + private static String computeDescription(RemoteDisplayInfo descriptor) { + final String description = descriptor.description; + return TextUtils.isEmpty(description) ? null : description; + } + + private static int computeSupportedTypes(RemoteDisplayInfo descriptor) { + return MediaRouter.ROUTE_TYPE_LIVE_AUDIO + | MediaRouter.ROUTE_TYPE_LIVE_VIDEO + | MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY; + } + + private static boolean computeEnabled(RemoteDisplayInfo descriptor) { + switch (descriptor.status) { + case RemoteDisplayInfo.STATUS_CONNECTED: + case RemoteDisplayInfo.STATUS_CONNECTING: + case RemoteDisplayInfo.STATUS_AVAILABLE: + return true; + default: + return false; + } + } + + private static int computeStatusCode(RemoteDisplayInfo descriptor) { + switch (descriptor.status) { + case RemoteDisplayInfo.STATUS_NOT_AVAILABLE: + return MediaRouter.RouteInfo.STATUS_NOT_AVAILABLE; + case RemoteDisplayInfo.STATUS_AVAILABLE: + return MediaRouter.RouteInfo.STATUS_AVAILABLE; + case RemoteDisplayInfo.STATUS_IN_USE: + return MediaRouter.RouteInfo.STATUS_IN_USE; + case RemoteDisplayInfo.STATUS_CONNECTING: + return MediaRouter.RouteInfo.STATUS_CONNECTING; + case RemoteDisplayInfo.STATUS_CONNECTED: + return MediaRouter.RouteInfo.STATUS_CONNECTED; + default: + return MediaRouter.RouteInfo.STATUS_NONE; + } + } + + private static int computePlaybackType(RemoteDisplayInfo descriptor) { + return MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE; + } + + private static int computePlaybackStream(RemoteDisplayInfo descriptor) { + return AudioSystem.STREAM_MUSIC; + } + + private static int computeVolume(RemoteDisplayInfo descriptor) { + final int volume = descriptor.volume; + final int volumeMax = descriptor.volumeMax; + if (volume < 0) { + return 0; + } else if (volume > volumeMax) { + return volumeMax; + } + return volume; + } + + private static int computeVolumeMax(RemoteDisplayInfo descriptor) { + final int volumeMax = descriptor.volumeMax; + return volumeMax > 0 ? volumeMax : 0; + } + + private static int computeVolumeHandling(RemoteDisplayInfo descriptor) { + final int volumeHandling = descriptor.volumeHandling; + switch (volumeHandling) { + case RemoteDisplayInfo.PLAYBACK_VOLUME_VARIABLE: + return MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE; + case RemoteDisplayInfo.PLAYBACK_VOLUME_FIXED: + default: + return MediaRouter.RouteInfo.PLAYBACK_VOLUME_FIXED; + } + } + + private static int computePresentationDisplayId(RemoteDisplayInfo descriptor) { + // The MediaRouter class validates that the id corresponds to an extant + // presentation display. So all we do here is canonicalize the null case. + final int displayId = descriptor.presentationDisplayId; + return displayId < 0 ? -1 : displayId; + } + } + } +} diff --git a/services/java/com/android/server/media/RemoteDisplayProviderProxy.java b/services/java/com/android/server/media/RemoteDisplayProviderProxy.java new file mode 100644 index 0000000..b248ee0 --- /dev/null +++ b/services/java/com/android/server/media/RemoteDisplayProviderProxy.java @@ -0,0 +1,443 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.media; + +import com.android.internal.util.Objects; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.media.IRemoteDisplayCallback; +import android.media.IRemoteDisplayProvider; +import android.media.RemoteDisplayState; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.IBinder.DeathRecipient; +import android.os.UserHandle; +import android.util.Log; +import android.util.Slog; + +import java.io.PrintWriter; +import java.lang.ref.WeakReference; + +/** + * Maintains a connection to a particular remote display provider service. + */ +final class RemoteDisplayProviderProxy implements ServiceConnection { + private static final String TAG = "RemoteDisplayProvider"; // max. 23 chars + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + private final Context mContext; + private final ComponentName mComponentName; + private final int mUserId; + private final Handler mHandler; + + private Callback mDisplayStateCallback; + + // Connection state + private boolean mRunning; + private boolean mBound; + private Connection mActiveConnection; + private boolean mConnectionReady; + + // Logical state + private int mDiscoveryMode; + private String mSelectedDisplayId; + private RemoteDisplayState mDisplayState; + private boolean mScheduledDisplayStateChangedCallback; + + public RemoteDisplayProviderProxy(Context context, ComponentName componentName, + int userId) { + mContext = context; + mComponentName = componentName; + mUserId = userId; + mHandler = new Handler(); + } + + public void dump(PrintWriter pw, String prefix) { + pw.println(prefix + "Proxy"); + pw.println(prefix + " mUserId=" + mUserId); + pw.println(prefix + " mRunning=" + mRunning); + pw.println(prefix + " mBound=" + mBound); + pw.println(prefix + " mActiveConnection=" + mActiveConnection); + pw.println(prefix + " mConnectionReady=" + mConnectionReady); + pw.println(prefix + " mDiscoveryMode=" + mDiscoveryMode); + pw.println(prefix + " mSelectedDisplayId=" + mSelectedDisplayId); + pw.println(prefix + " mDisplayState=" + mDisplayState); + } + + public void setCallback(Callback callback) { + mDisplayStateCallback = callback; + } + + public RemoteDisplayState getDisplayState() { + return mDisplayState; + } + + public void setDiscoveryMode(int mode) { + if (mDiscoveryMode != mode) { + mDiscoveryMode = mode; + if (mConnectionReady) { + mActiveConnection.setDiscoveryMode(mode); + } + updateBinding(); + } + } + + public void setSelectedDisplay(String id) { + if (!Objects.equal(mSelectedDisplayId, id)) { + if (mConnectionReady && mSelectedDisplayId != null) { + mActiveConnection.disconnect(mSelectedDisplayId); + } + mSelectedDisplayId = id; + if (mConnectionReady && id != null) { + mActiveConnection.connect(id); + } + updateBinding(); + } + } + + public void setDisplayVolume(int volume) { + if (mConnectionReady && mSelectedDisplayId != null) { + mActiveConnection.setVolume(mSelectedDisplayId, volume); + } + } + + public void adjustDisplayVolume(int delta) { + if (mConnectionReady && mSelectedDisplayId != null) { + mActiveConnection.adjustVolume(mSelectedDisplayId, delta); + } + } + + public boolean hasComponentName(String packageName, String className) { + return mComponentName.getPackageName().equals(packageName) + && mComponentName.getClassName().equals(className); + } + + public String getFlattenedComponentName() { + return mComponentName.flattenToShortString(); + } + + public void start() { + if (!mRunning) { + if (DEBUG) { + Slog.d(TAG, this + ": Starting"); + } + + mRunning = true; + updateBinding(); + } + } + + public void stop() { + if (mRunning) { + if (DEBUG) { + Slog.d(TAG, this + ": Stopping"); + } + + mRunning = false; + updateBinding(); + } + } + + public void rebindIfDisconnected() { + if (mActiveConnection == null && shouldBind()) { + unbind(); + bind(); + } + } + + private void updateBinding() { + if (shouldBind()) { + bind(); + } else { + unbind(); + } + } + + private boolean shouldBind() { + if (mRunning) { + // Bind whenever there is a discovery request or selected display. + if (mDiscoveryMode != RemoteDisplayState.DISCOVERY_MODE_NONE + || mSelectedDisplayId != null) { + return true; + } + } + return false; + } + + private void bind() { + if (!mBound) { + if (DEBUG) { + Slog.d(TAG, this + ": Binding"); + } + + Intent service = new Intent(RemoteDisplayState.SERVICE_INTERFACE); + service.setComponent(mComponentName); + try { + mBound = mContext.bindServiceAsUser(service, this, Context.BIND_AUTO_CREATE, + new UserHandle(mUserId)); + if (!mBound && DEBUG) { + Slog.d(TAG, this + ": Bind failed"); + } + } catch (SecurityException ex) { + if (DEBUG) { + Slog.d(TAG, this + ": Bind failed", ex); + } + } + } + } + + private void unbind() { + if (mBound) { + if (DEBUG) { + Slog.d(TAG, this + ": Unbinding"); + } + + mBound = false; + disconnect(); + mContext.unbindService(this); + } + } + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + if (DEBUG) { + Slog.d(TAG, this + ": Connected"); + } + + if (mBound) { + disconnect(); + + IRemoteDisplayProvider provider = IRemoteDisplayProvider.Stub.asInterface(service); + if (provider != null) { + Connection connection = new Connection(provider); + if (connection.register()) { + mActiveConnection = connection; + } else { + if (DEBUG) { + Slog.d(TAG, this + ": Registration failed"); + } + } + } else { + Slog.e(TAG, this + ": Service returned invalid remote display provider binder"); + } + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + if (DEBUG) { + Slog.d(TAG, this + ": Service disconnected"); + } + disconnect(); + } + + private void onConnectionReady(Connection connection) { + if (mActiveConnection == connection) { + mConnectionReady = true; + + if (mDiscoveryMode != RemoteDisplayState.DISCOVERY_MODE_NONE) { + mActiveConnection.setDiscoveryMode(mDiscoveryMode); + } + if (mSelectedDisplayId != null) { + mActiveConnection.connect(mSelectedDisplayId); + } + } + } + + private void onConnectionDied(Connection connection) { + if (mActiveConnection == connection) { + if (DEBUG) { + Slog.d(TAG, this + ": Service connection died"); + } + disconnect(); + } + } + + private void onDisplayStateChanged(Connection connection, RemoteDisplayState state) { + if (mActiveConnection == connection) { + if (DEBUG) { + Slog.d(TAG, this + ": State changed, state=" + state); + } + setDisplayState(state); + } + } + + private void disconnect() { + if (mActiveConnection != null) { + if (mSelectedDisplayId != null) { + mActiveConnection.disconnect(mSelectedDisplayId); + } + mConnectionReady = false; + mActiveConnection.dispose(); + mActiveConnection = null; + setDisplayState(null); + } + } + + private void setDisplayState(RemoteDisplayState state) { + if (!Objects.equal(mDisplayState, state)) { + mDisplayState = state; + if (!mScheduledDisplayStateChangedCallback) { + mScheduledDisplayStateChangedCallback = true; + mHandler.post(mDisplayStateChanged); + } + } + } + + @Override + public String toString() { + return "Service connection " + mComponentName.flattenToShortString(); + } + + private final Runnable mDisplayStateChanged = new Runnable() { + @Override + public void run() { + mScheduledDisplayStateChangedCallback = false; + if (mDisplayStateCallback != null) { + mDisplayStateCallback.onDisplayStateChanged( + RemoteDisplayProviderProxy.this, mDisplayState); + } + } + }; + + public interface Callback { + void onDisplayStateChanged(RemoteDisplayProviderProxy provider, RemoteDisplayState state); + } + + private final class Connection implements DeathRecipient { + private final IRemoteDisplayProvider mProvider; + private final ProviderCallback mCallback; + + public Connection(IRemoteDisplayProvider provider) { + mProvider = provider; + mCallback = new ProviderCallback(this); + } + + public boolean register() { + try { + mProvider.asBinder().linkToDeath(this, 0); + mProvider.setCallback(mCallback); + mHandler.post(new Runnable() { + @Override + public void run() { + onConnectionReady(Connection.this); + } + }); + return true; + } catch (RemoteException ex) { + binderDied(); + } + return false; + } + + public void dispose() { + mProvider.asBinder().unlinkToDeath(this, 0); + mCallback.dispose(); + } + + public void setDiscoveryMode(int mode) { + try { + mProvider.setDiscoveryMode(mode); + } catch (RemoteException ex) { + Slog.e(TAG, "Failed to deliver request to set discovery mode.", ex); + } + } + + public void connect(String id) { + try { + mProvider.connect(id); + } catch (RemoteException ex) { + Slog.e(TAG, "Failed to deliver request to connect to display.", ex); + } + } + + public void disconnect(String id) { + try { + mProvider.disconnect(id); + } catch (RemoteException ex) { + Slog.e(TAG, "Failed to deliver request to disconnect from display.", ex); + } + } + + public void setVolume(String id, int volume) { + try { + mProvider.setVolume(id, volume); + } catch (RemoteException ex) { + Slog.e(TAG, "Failed to deliver request to set display volume.", ex); + } + } + + public void adjustVolume(String id, int volume) { + try { + mProvider.adjustVolume(id, volume); + } catch (RemoteException ex) { + Slog.e(TAG, "Failed to deliver request to adjust display volume.", ex); + } + } + + @Override + public void binderDied() { + mHandler.post(new Runnable() { + @Override + public void run() { + onConnectionDied(Connection.this); + } + }); + } + + void postStateChanged(final RemoteDisplayState state) { + mHandler.post(new Runnable() { + @Override + public void run() { + onDisplayStateChanged(Connection.this, state); + } + }); + } + } + + /** + * Receives callbacks from the service. + * <p> + * This inner class is static and only retains a weak reference to the connection + * to prevent the client from being leaked in case the service is holding an + * active reference to the client's callback. + * </p> + */ + private static final class ProviderCallback extends IRemoteDisplayCallback.Stub { + private final WeakReference<Connection> mConnectionRef; + + public ProviderCallback(Connection connection) { + mConnectionRef = new WeakReference<Connection>(connection); + } + + public void dispose() { + mConnectionRef.clear(); + } + + @Override + public void onStateChanged(RemoteDisplayState state) throws RemoteException { + Connection connection = mConnectionRef.get(); + if (connection != null) { + connection.postStateChanged(state); + } + } + } +} diff --git a/services/java/com/android/server/media/RemoteDisplayProviderWatcher.java b/services/java/com/android/server/media/RemoteDisplayProviderWatcher.java new file mode 100644 index 0000000..6a5f563 --- /dev/null +++ b/services/java/com/android/server/media/RemoteDisplayProviderWatcher.java @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.media; + +import android.Manifest; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.media.RemoteDisplayState; +import android.os.Handler; +import android.os.UserHandle; +import android.util.Log; +import android.util.Slog; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; + +/** + * Watches for remote display provider services to be installed. + * Adds a provider to the media router for each registered service. + * + * @see RemoteDisplayProviderProxy + */ +public final class RemoteDisplayProviderWatcher { + private static final String TAG = "RemoteDisplayProvider"; // max. 23 chars + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + private final Context mContext; + private final Callback mCallback; + private final Handler mHandler; + private final int mUserId; + private final PackageManager mPackageManager; + + private final ArrayList<RemoteDisplayProviderProxy> mProviders = + new ArrayList<RemoteDisplayProviderProxy>(); + private boolean mRunning; + + public RemoteDisplayProviderWatcher(Context context, + Callback callback, Handler handler, int userId) { + mContext = context; + mCallback = callback; + mHandler = handler; + mUserId = userId; + mPackageManager = context.getPackageManager(); + } + + public void dump(PrintWriter pw, String prefix) { + pw.println(prefix + "Watcher"); + pw.println(prefix + " mUserId=" + mUserId); + pw.println(prefix + " mRunning=" + mRunning); + pw.println(prefix + " mProviders.size()=" + mProviders.size()); + } + + public void start() { + if (!mRunning) { + mRunning = true; + + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_PACKAGE_ADDED); + filter.addAction(Intent.ACTION_PACKAGE_REMOVED); + filter.addAction(Intent.ACTION_PACKAGE_CHANGED); + filter.addAction(Intent.ACTION_PACKAGE_REPLACED); + filter.addAction(Intent.ACTION_PACKAGE_RESTARTED); + filter.addDataScheme("package"); + mContext.registerReceiverAsUser(mScanPackagesReceiver, + new UserHandle(mUserId), filter, null, mHandler); + + // Scan packages. + // Also has the side-effect of restarting providers if needed. + mHandler.post(mScanPackagesRunnable); + } + } + + public void stop() { + if (mRunning) { + mRunning = false; + + mContext.unregisterReceiver(mScanPackagesReceiver); + mHandler.removeCallbacks(mScanPackagesRunnable); + + // Stop all providers. + for (int i = mProviders.size() - 1; i >= 0; i--) { + mProviders.get(i).stop(); + } + } + } + + private void scanPackages() { + if (!mRunning) { + return; + } + + // Add providers for all new services. + // Reorder the list so that providers left at the end will be the ones to remove. + int targetIndex = 0; + Intent intent = new Intent(RemoteDisplayState.SERVICE_INTERFACE); + for (ResolveInfo resolveInfo : mPackageManager.queryIntentServicesAsUser( + intent, 0, mUserId)) { + ServiceInfo serviceInfo = resolveInfo.serviceInfo; + if (serviceInfo != null && verifyServiceTrusted(serviceInfo)) { + int sourceIndex = findProvider(serviceInfo.packageName, serviceInfo.name); + if (sourceIndex < 0) { + RemoteDisplayProviderProxy provider = + new RemoteDisplayProviderProxy(mContext, + new ComponentName(serviceInfo.packageName, serviceInfo.name), + mUserId); + provider.start(); + mProviders.add(targetIndex++, provider); + mCallback.addProvider(provider); + } else if (sourceIndex >= targetIndex) { + RemoteDisplayProviderProxy provider = mProviders.get(sourceIndex); + provider.start(); // restart the provider if needed + provider.rebindIfDisconnected(); + Collections.swap(mProviders, sourceIndex, targetIndex++); + } + } + } + + // Remove providers for missing services. + if (targetIndex < mProviders.size()) { + for (int i = mProviders.size() - 1; i >= targetIndex; i--) { + RemoteDisplayProviderProxy provider = mProviders.get(i); + mCallback.removeProvider(provider); + mProviders.remove(provider); + provider.stop(); + } + } + } + + private boolean verifyServiceTrusted(ServiceInfo serviceInfo) { + if (serviceInfo.permission == null || !serviceInfo.permission.equals( + Manifest.permission.BIND_REMOTE_DISPLAY)) { + // If the service does not require this permission then any app could + // potentially bind to it and cause the remote display service to + // misbehave. So we only want to trust providers that require the + // correct permissions. + Slog.w(TAG, "Ignoring remote display provider service because it did not " + + "require the BIND_REMOTE_DISPLAY permission in its manifest: " + + serviceInfo.packageName + "/" + serviceInfo.name); + return false; + } + if (!hasCaptureVideoPermission(serviceInfo.packageName)) { + // If the service does not have permission to capture video then it + // isn't going to be terribly useful as a remote display, is it? + // Kind of makes you wonder what it's doing there in the first place. + Slog.w(TAG, "Ignoring remote display provider service because it does not " + + "have the CAPTURE_VIDEO_OUTPUT or CAPTURE_SECURE_VIDEO_OUTPUT " + + "permission: " + serviceInfo.packageName + "/" + serviceInfo.name); + return false; + } + // Looks good. + return true; + } + + private boolean hasCaptureVideoPermission(String packageName) { + if (mPackageManager.checkPermission(Manifest.permission.CAPTURE_VIDEO_OUTPUT, + packageName) == PackageManager.PERMISSION_GRANTED) { + return true; + } + if (mPackageManager.checkPermission(Manifest.permission.CAPTURE_SECURE_VIDEO_OUTPUT, + packageName) == PackageManager.PERMISSION_GRANTED) { + return true; + } + return false; + } + + private int findProvider(String packageName, String className) { + int count = mProviders.size(); + for (int i = 0; i < count; i++) { + RemoteDisplayProviderProxy provider = mProviders.get(i); + if (provider.hasComponentName(packageName, className)) { + return i; + } + } + return -1; + } + + private final BroadcastReceiver mScanPackagesReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (DEBUG) { + Slog.d(TAG, "Received package manager broadcast: " + intent); + } + scanPackages(); + } + }; + + private final Runnable mScanPackagesRunnable = new Runnable() { + @Override + public void run() { + scanPackages(); + } + }; + + public interface Callback { + void addProvider(RemoteDisplayProviderProxy provider); + void removeProvider(RemoteDisplayProviderProxy provider); + } +} diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 7291dd4..5450fd0 100755 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -1278,7 +1278,8 @@ public class PackageManagerService extends IPackageManager.Stub { frameworkDir.getPath(), OBSERVER_EVENTS, true, false); mFrameworkInstallObserver.startWatching(); scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM - | PackageParser.PARSE_IS_SYSTEM_DIR, + | PackageParser.PARSE_IS_SYSTEM_DIR + | PackageParser.PARSE_IS_PRIVILEGED, scanMode | SCAN_NO_DEX, 0); // Collected privileged system packages. @@ -1771,6 +1772,24 @@ public class PackageManagerService extends IPackageManager.Stub { state, userId); } + public boolean isPackageAvailable(String packageName, int userId) { + if (!sUserManager.exists(userId)) return false; + enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "is package available"); + synchronized (mPackages) { + PackageParser.Package p = mPackages.get(packageName); + if (p != null) { + final PackageSetting ps = (PackageSetting) p.mExtras; + if (ps != null) { + final PackageUserState state = ps.readUserState(userId); + if (state != null) { + return PackageParser.isAvailable(state); + } + } + } + } + return false; + } + @Override public PackageInfo getPackageInfo(String packageName, int flags, int userId) { if (!sUserManager.exists(userId)) return null; @@ -10011,11 +10030,11 @@ public class PackageManagerService extends IPackageManager.Stub { } if (filter.countDataAuthorities() != 0 || filter.countDataPaths() != 0 - || filter.countDataSchemes() != 0 + || filter.countDataSchemes() > 1 || filter.countDataTypes() != 0) { throw new IllegalArgumentException( "replacePreferredActivity expects filter to have no data authorities, " + - "paths, schemes or types."); + "paths, or types; and at most one scheme."); } synchronized (mPackages) { if (mContext.checkCallingOrSelfPermission( @@ -10032,33 +10051,27 @@ public class PackageManagerService extends IPackageManager.Stub { } final int callingUserId = UserHandle.getCallingUserId(); - ArrayList<PreferredActivity> removed = null; PreferredIntentResolver pir = mSettings.mPreferredActivities.get(callingUserId); if (pir != null) { - Iterator<PreferredActivity> it = pir.filterIterator(); - String action = filter.getAction(0); - String category = filter.getCategory(0); - while (it.hasNext()) { - PreferredActivity pa = it.next(); - if ((pa.countActions() == 0) || (pa.countCategories() == 0) - || (pa.getAction(0).equals(action) - && pa.getCategory(0).equals(category))) { - if (removed == null) { - removed = new ArrayList<PreferredActivity>(); - } - removed.add(pa); - if (DEBUG_PREFERRED) { - Slog.i(TAG, "Removing preferred activity " - + pa.mPref.mComponent + ":"); - filter.dump(new LogPrinter(Log.INFO, TAG), " "); - } - } - } - if (removed != null) { - for (int i=0; i<removed.size(); i++) { - PreferredActivity pa = removed.get(i); - pir.removeFilter(pa); + Intent intent = new Intent(filter.getAction(0)).addCategory(filter.getCategory(0)); + if (filter.countDataSchemes() == 1) { + Uri.Builder builder = new Uri.Builder(); + builder.scheme(filter.getDataScheme(0)); + intent.setData(builder.build()); + } + List<PreferredActivity> matches = pir.queryIntent( + intent, null, true, callingUserId); + if (DEBUG_PREFERRED) { + Slog.i(TAG, matches.size() + " preferred matches for " + intent); + } + for (int i = 0; i < matches.size(); i++) { + PreferredActivity pa = matches.get(i); + if (DEBUG_PREFERRED) { + Slog.i(TAG, "Removing preferred activity " + + pa.mPref.mComponent + ":"); + filter.dump(new LogPrinter(Log.INFO, TAG), " "); } + pir.removeFilter(pa); } } addPreferredActivityInternal(filter, match, set, activity, true, callingUserId); diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java index d471b57..f2efde1 100644 --- a/services/java/com/android/server/wifi/WifiService.java +++ b/services/java/com/android/server/wifi/WifiService.java @@ -369,15 +369,17 @@ public final class WifiService extends IWifiManager.Stub { } private class BatchedScanRequest extends DeathRecipient { - BatchedScanSettings settings; - int uid; - int pid; + final BatchedScanSettings settings; + final int uid; + final int pid; + final WorkSource workSource; - BatchedScanRequest(BatchedScanSettings settings, IBinder binder) { + BatchedScanRequest(BatchedScanSettings settings, IBinder binder, WorkSource ws) { super(0, null, binder, null); this.settings = settings; this.uid = getCallingUid(); this.pid = getCallingPid(); + workSource = ws; } public void binderDied() { stopBatchedScan(settings, uid, pid); @@ -406,12 +408,19 @@ public final class WifiService extends IWifiManager.Stub { /** * see {@link android.net.wifi.WifiManager#requestBatchedScan()} */ - public boolean requestBatchedScan(BatchedScanSettings requested, IBinder binder) { + public boolean requestBatchedScan(BatchedScanSettings requested, IBinder binder, + WorkSource workSource) { enforceChangePermission(); + if (workSource != null) { + enforceWorkSourcePermission(); + // WifiManager currently doesn't use names, so need to clear names out of the + // supplied WorkSource to allow future WorkSource combining. + workSource.clearNames(); + } if (mBatchedScanSupported == false) return false; requested = new BatchedScanSettings(requested); if (requested.isInvalid()) return false; - BatchedScanRequest r = new BatchedScanRequest(requested, binder); + BatchedScanRequest r = new BatchedScanRequest(requested, binder, workSource); synchronized(mBatchedScanners) { mBatchedScanners.add(r); resolveBatchedScannersLocked(); @@ -468,18 +477,48 @@ public final class WifiService extends IWifiManager.Stub { private void resolveBatchedScannersLocked() { BatchedScanSettings setting = new BatchedScanSettings(); + WorkSource responsibleWorkSource = null; int responsibleUid = 0; + double responsibleCsph = 0; // Channel Scans Per Hour if (mBatchedScanners.size() == 0) { - mWifiStateMachine.setBatchedScanSettings(null, 0); + mWifiStateMachine.setBatchedScanSettings(null, 0, 0, null); return; } for (BatchedScanRequest r : mBatchedScanners) { BatchedScanSettings s = r.settings; + + // evaluate responsibility + int currentChannelCount; + int currentScanInterval; + double currentCsph; + + if (s.channelSet == null || s.channelSet.isEmpty()) { + // all channels - 11 B and 9 A channels roughly. + currentChannelCount = 9 + 11; + } else { + currentChannelCount = s.channelSet.size(); + // these are rough est - no real need to correct for reg-domain; + if (s.channelSet.contains("A")) currentChannelCount += (9 - 1); + if (s.channelSet.contains("B")) currentChannelCount += (11 - 1); + + } + if (s.scanIntervalSec == BatchedScanSettings.UNSPECIFIED) { + currentScanInterval = BatchedScanSettings.DEFAULT_INTERVAL_SEC; + } else { + currentScanInterval = s.scanIntervalSec; + } + currentCsph = 60 * 60 * currentChannelCount / currentScanInterval; + + if (currentCsph > responsibleCsph) { + responsibleUid = r.uid; + responsibleWorkSource = r.workSource; + responsibleCsph = currentCsph; + } + if (s.maxScansPerBatch != BatchedScanSettings.UNSPECIFIED && s.maxScansPerBatch < setting.maxScansPerBatch) { setting.maxScansPerBatch = s.maxScansPerBatch; - responsibleUid = r.uid; } if (s.maxApPerScan != BatchedScanSettings.UNSPECIFIED && (setting.maxApPerScan == BatchedScanSettings.UNSPECIFIED || @@ -489,7 +528,6 @@ public final class WifiService extends IWifiManager.Stub { if (s.scanIntervalSec != BatchedScanSettings.UNSPECIFIED && s.scanIntervalSec < setting.scanIntervalSec) { setting.scanIntervalSec = s.scanIntervalSec; - responsibleUid = r.uid; } if (s.maxApForDistance != BatchedScanSettings.UNSPECIFIED && (setting.maxApForDistance == BatchedScanSettings.UNSPECIFIED || @@ -511,7 +549,8 @@ public final class WifiService extends IWifiManager.Stub { } setting.constrain(); - mWifiStateMachine.setBatchedScanSettings(setting, responsibleUid); + mWifiStateMachine.setBatchedScanSettings(setting, responsibleUid, (int)responsibleCsph, + responsibleWorkSource); } private void enforceAccessPermission() { diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java index 8cc1d02..e98014b 100644 --- a/services/java/com/android/server/wm/AppWindowToken.java +++ b/services/java/com/android/server/wm/AppWindowToken.java @@ -53,6 +53,7 @@ class AppWindowToken extends WindowToken { int groupId = -1; boolean appFullscreen; int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; + boolean layoutConfigChanges; boolean showWhenLocked; // The input dispatching timeout for this application token in nanoseconds. diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java index 52f2325..d358b4c 100644 --- a/services/java/com/android/server/wm/DisplayContent.java +++ b/services/java/com/android/server/wm/DisplayContent.java @@ -25,9 +25,11 @@ import android.app.ActivityManager.StackBoxInfo; import android.graphics.Rect; import android.graphics.Region; import android.os.Debug; +import android.util.EventLog; import android.util.Slog; import android.view.Display; import android.view.DisplayInfo; +import com.android.server.EventLogTags; import java.io.PrintWriter; import java.util.ArrayList; @@ -97,9 +99,6 @@ class DisplayContent { /** True when the home StackBox is at the top of mStackBoxes, false otherwise. */ private TaskStack mHomeStack = null; - /** Sorted most recent at top, oldest at [0]. */ - ArrayList<TaskStack> mStackHistory = new ArrayList<TaskStack>(); - /** Detect user tapping outside of current focused stack bounds .*/ StackTapPointerEventListener mTapDetector; @@ -107,7 +106,7 @@ class DisplayContent { Region mTouchExcludeRegion = new Region(); /** Save allocating when retrieving tasks */ - ArrayList<Task> mTaskHistory = new ArrayList<Task>(); + private ArrayList<Task> mTaskHistory = new ArrayList<Task>(); /** Save allocating when calculating rects */ Rect mTmpRect = new Rect(); @@ -160,12 +159,6 @@ class DisplayContent { return mStackBoxes.get(0).mStack != mHomeStack; } - void moveStack(TaskStack stack, boolean toTop) { - mStackHistory.remove(stack); - mStackHistory.add(toTop ? mStackHistory.size() : 0, stack); - mService.moveStackWindowsLocked(this); - } - public boolean isPrivate() { return (mDisplay.getFlags() & Display.FLAG_PRIVATE) != 0; } @@ -200,6 +193,7 @@ class DisplayContent { } mTaskHistory.add(taskNdx, task); + EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.taskId, toTop ? 1 : 0, taskNdx); } void removeTask(Task task) { @@ -277,6 +271,8 @@ class DisplayContent { if (newStack != null) { layoutNeeded = true; } + EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, relativeStackBoxId, position, + (int)(weight * 100 + 0.5)); return newStack; } @@ -345,6 +341,7 @@ class DisplayContent { boolean moveHomeStackBox(boolean toTop) { if (DEBUG_STACK) Slog.d(TAG, "moveHomeStackBox: toTop=" + toTop + " Callers=" + Debug.getCallers(4)); + EventLog.writeEvent(EventLogTags.WM_HOME_STACK_MOVED, toTop ? 1 : 0); switch (mStackBoxes.size()) { case 0: throw new RuntimeException("moveHomeStackBox: No home StackBox!"); case 1: return false; // Only the home StackBox exists. diff --git a/services/java/com/android/server/wm/StackBox.java b/services/java/com/android/server/wm/StackBox.java index d054e9a..d351925 100644 --- a/services/java/com/android/server/wm/StackBox.java +++ b/services/java/com/android/server/wm/StackBox.java @@ -243,10 +243,6 @@ public class StackBox { /** Remove this box and propagate its sibling's content up to their parent. * @return The first stackId of the resulting StackBox. */ int remove() { - if (mStack != null) { - if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: removing stackId=" + mStack.mStackId); - mDisplayContent.mStackHistory.remove(mStack); - } mDisplayContent.layoutNeeded = true; if (mParent == null) { diff --git a/services/java/com/android/server/wm/Task.java b/services/java/com/android/server/wm/Task.java index d9acbb9..13fdbc8 100644 --- a/services/java/com/android/server/wm/Task.java +++ b/services/java/com/android/server/wm/Task.java @@ -16,6 +16,9 @@ package com.android.server.wm; +import android.util.EventLog; +import com.android.server.EventLogTags; + class Task { // private final String TAG = "TaskGroup"; TaskStack mStack; @@ -41,6 +44,8 @@ class Task { boolean removeAppToken(AppWindowToken wtoken) { mAppTokens.remove(wtoken); if (mAppTokens.size() == 0) { + EventLog.writeEvent(com.android.server.EventLogTags.WM_TASK_REMOVED, taskId, + "removeAppToken: last token"); mStack.removeTask(this); return true; } diff --git a/services/java/com/android/server/wm/TaskStack.java b/services/java/com/android/server/wm/TaskStack.java index 34bef68..cb29df4 100644 --- a/services/java/com/android/server/wm/TaskStack.java +++ b/services/java/com/android/server/wm/TaskStack.java @@ -21,8 +21,10 @@ import static com.android.server.wm.WindowManagerService.TAG; import android.graphics.Rect; import android.os.Debug; +import android.util.EventLog; import android.util.Slog; import android.util.TypedValue; +import com.android.server.EventLogTags; import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; @@ -45,7 +47,7 @@ public class TaskStack { /** The Tasks that define this stack. Oldest Tasks are at the bottom. The ordering must match * mTaskHistory in the ActivityStack with the same mStackId */ - private ArrayList<Task> mTasks = new ArrayList<Task>(); + private final ArrayList<Task> mTasks = new ArrayList<Task>(); /** The StackBox this sits in. */ StackBox mStackBox; @@ -70,7 +72,6 @@ public class TaskStack { mService = service; mStackId = stackId; mDisplayContent = displayContent; - final int displayId = displayContent.getDisplayId(); mDimLayer = new DimLayer(service, this); mAnimationBackgroundSurface = new DimLayer(service, this); } @@ -152,6 +153,7 @@ public class TaskStack { int remove() { mAnimationBackgroundSurface.destroySurface(); mDimLayer.destroySurface(); + EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId); return mStackBox.remove(); } @@ -269,6 +271,8 @@ public class TaskStack { for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { final WindowState win = windows.get(winNdx); if (!resizingWindows.contains(win)) { + if (WindowManagerService.DEBUG_RESIZE) Slog.d(TAG, + "setBounds: Resizing " + win); resizingWindows.add(win); } win.mUnderStatusBar = underStatusBar; diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java index cd46bb8..91f15f3 100644 --- a/services/java/com/android/server/wm/WindowAnimator.java +++ b/services/java/com/android/server/wm/WindowAnimator.java @@ -245,7 +245,7 @@ public class WindowAnimator { mForceHiding = KEYGUARD_ANIMATING_OUT; } } else { - mForceHiding = KEYGUARD_SHOWN; + mForceHiding = win.isDrawnLw() ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN; } } if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index e1e9f5c..3ed5076 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -578,10 +578,13 @@ public class WindowManagerService extends IWindowManager.Stub private boolean mUpdateRotation = false; boolean mWallpaperActionPending = false; - private static final int DISPLAY_CONTENT_UNKNOWN = 0; - private static final int DISPLAY_CONTENT_MIRROR = 1; - private static final int DISPLAY_CONTENT_UNIQUE = 2; - private int mDisplayHasContent = DISPLAY_CONTENT_UNKNOWN; + // Set to true when the display contains content to show the user. + // When false, the display manager may choose to mirror or blank the display. + boolean mDisplayHasContent = false; + + // Only set while traversing the default display based on its content. + // Affects the behavior of mirroring on secondary displays. + boolean mObscureApplicationContentOnSecondaryDisplays = false; } final LayoutFields mInnerFields = new LayoutFields(); @@ -3394,16 +3397,17 @@ public class WindowManagerService extends IWindowManager.Stub if (stack == null) { throw new IllegalArgumentException("addAppToken: invalid stackId=" + stackId); } + EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId); Task task = new Task(atoken, stack, userId); mTaskIdToTask.put(taskId, task); stack.addTask(task, true); - stack.getDisplayContent().moveStack(stack, true); return task; } @Override public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId, - int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId) { + int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId, + int configChanges) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "addAppToken()")) { throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); @@ -3435,6 +3439,8 @@ public class WindowManagerService extends IWindowManager.Stub atoken.appFullscreen = fullscreen; atoken.showWhenLocked = showWhenLocked; atoken.requestedOrientation = requestedOrientation; + atoken.layoutConfigChanges = (configChanges & + (ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0; if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken + " to stack=" + stackId + " task=" + taskId + " at " + addPos); @@ -4303,10 +4309,6 @@ public class WindowManagerService extends IWindowManager.Stub // If we are preparing an app transition, then delay changing // the visibility of this token until we execute that transition. if (okToDisplay() && mAppTransition.isTransitionSet()) { - // Already in requested state, don't do anything more. - if (wtoken.hiddenRequested != visible) { - return; - } wtoken.hiddenRequested = !visible; if (!wtoken.startingDisplayed) { @@ -4792,7 +4794,6 @@ public class WindowManagerService extends IWindowManager.Stub displayContent.moveHomeStackBox(isHomeStackTask); } stack.moveTaskToTop(task); - displayContent.moveStack(stack, true); } } finally { Binder.restoreCallingIdentity(origId); @@ -4846,7 +4847,6 @@ public class WindowManagerService extends IWindowManager.Stub weight); if (stack != null) { mStackIdToStack.put(stackId, stack); - displayContent.moveStack(stack, true); performLayoutAndPlaceSurfacesLocked(); return; } @@ -4878,6 +4878,7 @@ public class WindowManagerService extends IWindowManager.Stub return; } final TaskStack stack = task.mStack; + EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, taskId, "removeTask"); stack.removeTask(task); stack.getDisplayContent().layoutNeeded = true; } @@ -8269,8 +8270,9 @@ public class WindowManagerService extends IWindowManager.Stub // windows, since that means "perform layout as normal, // just don't display"). if (!gone || !win.mHaveFrame || win.mLayoutNeeded - || win.mAttrs.type == TYPE_KEYGUARD && win.isConfigChanged() - || mOpeningApps.contains(win.mAppToken) + || ((win.isConfigChanged() || win.setInsetsChanged()) && + (win.mAttrs.type == TYPE_KEYGUARD || + win.mAppToken != null && win.mAppToken.layoutConfigChanges)) || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) { if (!win.mLayoutAttached) { if (initial) { @@ -8704,12 +8706,7 @@ public class WindowManagerService extends IWindowManager.Stub private void updateResizingWindows(final WindowState w) { final WindowStateAnimator winAnimator = w.mWinAnimator; if (w.mHasSurface && w.mLayoutSeq == mLayoutSeq) { - w.mOverscanInsetsChanged |= - !w.mLastOverscanInsets.equals(w.mOverscanInsets); - w.mContentInsetsChanged |= - !w.mLastContentInsets.equals(w.mContentInsets); - w.mVisibleInsetsChanged |= - !w.mLastVisibleInsets.equals(w.mVisibleInsets); + w.setInsetsChanged(); boolean configChanged = w.isConfigChanged(); if (DEBUG_CONFIGURATION && configChanged) { Slog.v(TAG, "Win " + w + " config changed: " @@ -8784,6 +8781,14 @@ public class WindowManagerService extends IWindowManager.Stub final WindowManager.LayoutParams attrs = w.mAttrs; final int attrFlags = attrs.flags; final boolean canBeSeen = w.isDisplayedLw(); + final boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); + + if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { + // This window completely covers everything behind it, + // so we want to leave all of them as undimmed (for + // performance reasons). + mInnerFields.mObscured = true; + } if (w.mHasSurface) { if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { @@ -8812,22 +8817,24 @@ public class WindowManagerService extends IWindowManager.Stub } if (canBeSeen) { - if (type == TYPE_DREAM || type == TYPE_KEYGUARD) { - mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_MIRROR; - } else if (mInnerFields.mDisplayHasContent - == LayoutFields.DISPLAY_CONTENT_UNKNOWN) { - mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNIQUE; + // This function assumes that the contents of the default display are + // processed first before secondary displays. + if (w.mDisplayContent.isDefaultDisplay) { + // While a dream or keyguard is showing, obscure ordinary application + // content on secondary displays (by forcibly enabling mirroring unless + // there is other content we want to show) but still allow opaque + // keyguard dialogs to be shown. + if (type == TYPE_DREAM || type == TYPE_KEYGUARD) { + mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true; + } + mInnerFields.mDisplayHasContent = true; + } else if (!mInnerFields.mObscureApplicationContentOnSecondaryDisplays + || (mInnerFields.mObscured && type == TYPE_KEYGUARD_DIALOG)) { + // Allow full screen keyguard presentation dialogs to be seen. + mInnerFields.mDisplayHasContent = true; } } } - - boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn(); - if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) { - // This window completely covers everything behind it, - // so we want to leave all of them as undimmed (for - // performance reasons). - mInnerFields.mObscured = true; - } } private void handleFlagDimBehind(WindowState w, int innerDw, int innerDh) { @@ -8905,7 +8912,7 @@ public class WindowManagerService extends IWindowManager.Stub mInnerFields.mScreenBrightness = -1; mInnerFields.mButtonBrightness = -1; mInnerFields.mUserActivityTimeout = -1; - mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN; + mInnerFields.mObscureApplicationContentOnSecondaryDisplays = false; mTransactionSequence++; @@ -8940,10 +8947,8 @@ public class WindowManagerService extends IWindowManager.Stub final int innerDh = displayInfo.appHeight; final boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY); - // Reset for each display unless we are forcing mirroring. - if (mInnerFields.mDisplayHasContent != LayoutFields.DISPLAY_CONTENT_MIRROR) { - mInnerFields.mDisplayHasContent = LayoutFields.DISPLAY_CONTENT_UNKNOWN; - } + // Reset for each display. + mInnerFields.mDisplayHasContent = false; int repeats = 0; do { @@ -9152,20 +9157,8 @@ public class WindowManagerService extends IWindowManager.Stub updateResizingWindows(w); } - final boolean hasUniqueContent; - switch (mInnerFields.mDisplayHasContent) { - case LayoutFields.DISPLAY_CONTENT_MIRROR: - hasUniqueContent = isDefaultDisplay; - break; - case LayoutFields.DISPLAY_CONTENT_UNIQUE: - hasUniqueContent = true; - break; - case LayoutFields.DISPLAY_CONTENT_UNKNOWN: - default: - hasUniqueContent = false; - break; - } - mDisplayManagerService.setDisplayHasContent(displayId, hasUniqueContent, + mDisplayManagerService.setDisplayHasContent(displayId, + mInnerFields.mDisplayHasContent, true /* inTraversal, must call performTraversalInTrans... below */); getDisplayContentLocked(displayId).stopDimmingIfNeeded(); diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java index 2d08792..4d53cea 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/java/com/android/server/wm/WindowState.java @@ -701,6 +701,13 @@ final class WindowState implements WindowManagerPolicy.WindowState { return mAppToken != null ? mAppToken.appToken : null; } + boolean setInsetsChanged() { + mOverscanInsetsChanged |= !mLastOverscanInsets.equals(mOverscanInsets); + mContentInsetsChanged |= !mLastContentInsets.equals(mContentInsets); + mVisibleInsetsChanged |= !mLastVisibleInsets.equals(mVisibleInsets); + return mOverscanInsetsChanged || mContentInsetsChanged || mVisibleInsetsChanged; + } + public int getDisplayId() { return mDisplayContent.getDisplayId(); } diff --git a/tests/RemoteDisplayProvider/Android.mk b/tests/RemoteDisplayProvider/Android.mk new file mode 100644 index 0000000..2f4b343 --- /dev/null +++ b/tests/RemoteDisplayProvider/Android.mk @@ -0,0 +1,26 @@ +# Copyright (C) 2013 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. + +LOCAL_PATH := $(call my-dir) + +# Build the application. +include $(CLEAR_VARS) +LOCAL_PACKAGE_NAME := RemoteDisplayProviderTest +LOCAL_MODULE_TAGS := tests +LOCAL_SDK_VERSION := current +LOCAL_SRC_FILES := $(call all-java-files-under, src) +LOCAL_RESOURCE_DIR = $(LOCAL_PATH)/res +LOCAL_JAVA_LIBRARIES := com.android.media.remotedisplay +LOCAL_CERTIFICATE := platform +include $(BUILD_PACKAGE) diff --git a/tests/RemoteDisplayProvider/AndroidManifest.xml b/tests/RemoteDisplayProvider/AndroidManifest.xml new file mode 100644 index 0000000..afb7c78 --- /dev/null +++ b/tests/RemoteDisplayProvider/AndroidManifest.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.media.remotedisplay.test" > + + <uses-sdk android:minSdkVersion="19" /> + <uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"/> + + <application android:label="@string/app_name" + android:icon="@drawable/ic_app"> + <uses-library android:name="com.android.media.remotedisplay" + android:required="true" /> + + <service android:name=".RemoteDisplayProviderService" + android:label="@string/app_name" + android:exported="true" + android:permission="android.permission.BIND_REMOTE_DISPLAY"> + <intent-filter> + <action android:name="com.android.media.remotedisplay.RemoteDisplayProvider"/> + </intent-filter> + </service> + + </application> +</manifest> diff --git a/tests/RemoteDisplayProvider/README b/tests/RemoteDisplayProvider/README new file mode 100644 index 0000000..8bf0130 --- /dev/null +++ b/tests/RemoteDisplayProvider/README @@ -0,0 +1,16 @@ +This directory contains sample code to test system integration with +remote display providers using the API declared by the +com.android.media.remotedisplay.jar library. + +--- DESCRIPTION --- + +The application registers a service that publishes a few different +remote display routes. Behavior can be controlled by modifying the +code. + +To exercise the provider, use System UI features for connecting to +wireless displays or launch an activity that uses the MediaRouter, +such as the PresentationWithMediaRouterActivity in ApiDemos. + +This code is mainly intended for development and not meant to be +used as an example implementation of a robust remote display provider. diff --git a/tests/RemoteDisplayProvider/res/drawable-hdpi/ic_app.png b/tests/RemoteDisplayProvider/res/drawable-hdpi/ic_app.png Binary files differnew file mode 100755 index 0000000..66a1984 --- /dev/null +++ b/tests/RemoteDisplayProvider/res/drawable-hdpi/ic_app.png diff --git a/tests/RemoteDisplayProvider/res/drawable-mdpi/ic_app.png b/tests/RemoteDisplayProvider/res/drawable-mdpi/ic_app.png Binary files differnew file mode 100644 index 0000000..5ae7701 --- /dev/null +++ b/tests/RemoteDisplayProvider/res/drawable-mdpi/ic_app.png diff --git a/tests/RemoteDisplayProvider/res/values/strings.xml b/tests/RemoteDisplayProvider/res/values/strings.xml new file mode 100644 index 0000000..dd82d2c --- /dev/null +++ b/tests/RemoteDisplayProvider/res/values/strings.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 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. +--> + +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="app_name">Remote Display Provider Test</string> +</resources> diff --git a/tests/RemoteDisplayProvider/src/com/android/media/remotedisplay/test/RemoteDisplayProviderService.java b/tests/RemoteDisplayProvider/src/com/android/media/remotedisplay/test/RemoteDisplayProviderService.java new file mode 100644 index 0000000..611d7e4 --- /dev/null +++ b/tests/RemoteDisplayProvider/src/com/android/media/remotedisplay/test/RemoteDisplayProviderService.java @@ -0,0 +1,321 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.media.remotedisplay.test; + +import com.android.media.remotedisplay.RemoteDisplay; +import com.android.media.remotedisplay.RemoteDisplayProvider; + +import android.app.Service; +import android.content.Intent; +import android.os.Handler; +import android.os.IBinder; +import android.util.Log; + +/** + * Remote display provider implementation that publishes working routes. + */ +public class RemoteDisplayProviderService extends Service { + private static final String TAG = "RemoteDisplayProviderTest"; + + private Provider mProvider; + + @Override + public IBinder onBind(Intent intent) { + if (intent.getAction().equals(RemoteDisplayProvider.SERVICE_INTERFACE)) { + if (mProvider == null) { + mProvider = new Provider(); + return mProvider.getBinder(); + } + } + return null; + } + + final class Provider extends RemoteDisplayProvider { + private RemoteDisplay mTestDisplay1; // variable volume + private RemoteDisplay mTestDisplay2; // fixed volume + private RemoteDisplay mTestDisplay3; // not available + private RemoteDisplay mTestDisplay4; // in use + private RemoteDisplay mTestDisplay5; // available but ignores request to connect + private RemoteDisplay mTestDisplay6; // available but never finishes connecting + private RemoteDisplay mTestDisplay7; // blinks in and out of existence + private RemoteDisplay mTestDisplay8; // available but connecting attempt flakes out + private RemoteDisplay mTestDisplay9; // available but connection flakes out + private RemoteDisplay mTestDisplay10; // available and reconnects periodically + + private final Handler mHandler; + private boolean mBlinking; + + public Provider() { + super(RemoteDisplayProviderService.this); + mHandler = new Handler(getMainLooper()); + } + + @Override + public void onDiscoveryModeChanged(int mode) { + Log.d(TAG, "onDiscoveryModeChanged: mode=" + mode); + + if (mode != DISCOVERY_MODE_NONE) { + // When discovery begins, go find all of the routes. + if (mTestDisplay1 == null) { + mTestDisplay1 = new RemoteDisplay("testDisplay1", + "Test Display 1 (variable)"); + mTestDisplay1.setDescription("Variable volume"); + mTestDisplay1.setStatus(RemoteDisplay.STATUS_AVAILABLE); + mTestDisplay1.setVolume(10); + mTestDisplay1.setVolumeHandling(RemoteDisplay.PLAYBACK_VOLUME_VARIABLE); + mTestDisplay1.setVolumeMax(15); + addDisplay(mTestDisplay1); + } + if (mTestDisplay2 == null) { + mTestDisplay2 = new RemoteDisplay("testDisplay2", + "Test Display 2 (fixed)"); + mTestDisplay2.setDescription("Fixed volume"); + mTestDisplay2.setStatus(RemoteDisplay.STATUS_AVAILABLE); + addDisplay(mTestDisplay2); + } + if (mTestDisplay3 == null) { + mTestDisplay3 = new RemoteDisplay("testDisplay3", + "Test Display 3 (unavailable)"); + mTestDisplay3.setDescription("Always unavailable"); + mTestDisplay3.setStatus(RemoteDisplay.STATUS_NOT_AVAILABLE); + addDisplay(mTestDisplay3); + } + if (mTestDisplay4 == null) { + mTestDisplay4 = new RemoteDisplay("testDisplay4", + "Test Display 4 (in-use)"); + mTestDisplay4.setDescription("Always in-use"); + mTestDisplay4.setStatus(RemoteDisplay.STATUS_IN_USE); + addDisplay(mTestDisplay4); + } + if (mTestDisplay5 == null) { + mTestDisplay5 = new RemoteDisplay("testDisplay5", + "Test Display 5 (connect ignored)"); + mTestDisplay5.setDescription("Ignores connect"); + mTestDisplay5.setStatus(RemoteDisplay.STATUS_AVAILABLE); + addDisplay(mTestDisplay5); + } + if (mTestDisplay6 == null) { + mTestDisplay6 = new RemoteDisplay("testDisplay6", + "Test Display 6 (connect hangs)"); + mTestDisplay6.setDescription("Never finishes connecting"); + mTestDisplay6.setStatus(RemoteDisplay.STATUS_AVAILABLE); + addDisplay(mTestDisplay6); + } + if (mTestDisplay8 == null) { + mTestDisplay8 = new RemoteDisplay("testDisplay8", + "Test Display 8 (flaky when connecting)"); + mTestDisplay8.setDescription("Aborts spontaneously while connecting"); + mTestDisplay8.setStatus(RemoteDisplay.STATUS_AVAILABLE); + addDisplay(mTestDisplay8); + } + if (mTestDisplay9 == null) { + mTestDisplay9 = new RemoteDisplay("testDisplay9", + "Test Display 9 (flaky when connected)"); + mTestDisplay9.setDescription("Aborts spontaneously while connected"); + mTestDisplay9.setStatus(RemoteDisplay.STATUS_AVAILABLE); + addDisplay(mTestDisplay9); + } + if (mTestDisplay10 == null) { + mTestDisplay10 = new RemoteDisplay("testDisplay10", + "Test Display 10 (reconnects periodically)"); + mTestDisplay10.setDescription("Reconnects spontaneously"); + mTestDisplay10.setStatus(RemoteDisplay.STATUS_AVAILABLE); + addDisplay(mTestDisplay10); + } + } else { + // When discovery ends, go hide some of the routes we can't actually use. + // This isn't something a normal route provider would do though. + // The routes will usually stay published. + if (mTestDisplay3 != null) { + removeDisplay(mTestDisplay3); + mTestDisplay3 = null; + } + if (mTestDisplay4 != null) { + removeDisplay(mTestDisplay4); + mTestDisplay4 = null; + } + } + + // When active discovery is on, pretend there's a route that we can't quite + // reach that blinks in and out of existence. + if (mode == DISCOVERY_MODE_ACTIVE) { + if (!mBlinking) { + mBlinking = true; + mHandler.post(mBlink); + } + } else { + mBlinking = false; + } + } + + @Override + public void onConnect(final RemoteDisplay display) { + Log.d(TAG, "onConnect: display.getId()=" + display.getId()); + + if (display == mTestDisplay1 || display == mTestDisplay2) { + display.setStatus(RemoteDisplay.STATUS_CONNECTING); + updateDisplay(display); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + if ((display == mTestDisplay1 || display == mTestDisplay2) + && display.getStatus() == RemoteDisplay.STATUS_CONNECTING) { + display.setStatus(RemoteDisplay.STATUS_CONNECTED); + updateDisplay(display); + } + } + }, 2000); + } else if (display == mTestDisplay6 || display == mTestDisplay7) { + // never finishes connecting + display.setStatus(RemoteDisplay.STATUS_CONNECTING); + updateDisplay(display); + } else if (display == mTestDisplay8) { + // flakes out while connecting + display.setStatus(RemoteDisplay.STATUS_CONNECTING); + updateDisplay(display); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + if ((display == mTestDisplay8) + && display.getStatus() == RemoteDisplay.STATUS_CONNECTING) { + display.setStatus(RemoteDisplay.STATUS_AVAILABLE); + updateDisplay(display); + } + } + }, 2000); + } else if (display == mTestDisplay9) { + // flakes out when connected + display.setStatus(RemoteDisplay.STATUS_CONNECTING); + updateDisplay(display); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + if ((display == mTestDisplay9) + && display.getStatus() == RemoteDisplay.STATUS_CONNECTING) { + display.setStatus(RemoteDisplay.STATUS_CONNECTED); + updateDisplay(display); + } + } + }, 2000); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + if ((display == mTestDisplay9) + && display.getStatus() == RemoteDisplay.STATUS_CONNECTED) { + display.setStatus(RemoteDisplay.STATUS_AVAILABLE); + updateDisplay(display); + } + } + }, 5000); + } else if (display == mTestDisplay10) { + display.setStatus(RemoteDisplay.STATUS_CONNECTING); + updateDisplay(display); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + if (display == mTestDisplay10) { + if (display.getStatus() == RemoteDisplay.STATUS_CONNECTING) { + display.setStatus(RemoteDisplay.STATUS_CONNECTED); + updateDisplay(display); + mHandler.postDelayed(this, 7000); + } else if (display.getStatus() == RemoteDisplay.STATUS_CONNECTED) { + display.setStatus(RemoteDisplay.STATUS_CONNECTING); + updateDisplay(display); + mHandler.postDelayed(this, 2000); + } + } + } + }, 2000); + } + } + + @Override + public void onDisconnect(RemoteDisplay display) { + Log.d(TAG, "onDisconnect: display.getId()=" + display.getId()); + + if (display == mTestDisplay1 || display == mTestDisplay2 + || display == mTestDisplay6 || display == mTestDisplay8 + || display == mTestDisplay9 || display == mTestDisplay10) { + display.setStatus(RemoteDisplay.STATUS_AVAILABLE); + updateDisplay(display); + } + } + + @Override + public void onSetVolume(RemoteDisplay display, int volume) { + Log.d(TAG, "onSetVolume: display.getId()=" + display.getId() + + ", volume=" + volume); + + if (display == mTestDisplay1) { + display.setVolume(Math.max(0, Math.min(display.getVolumeMax(), volume))); + updateDisplay(display); + } + } + + @Override + public void onAdjustVolume(RemoteDisplay display, int delta) { + Log.d(TAG, "onAdjustVolume: display.getId()=" + display.getId() + + ", delta=" + delta); + + if (display == mTestDisplay1) { + display.setVolume(Math.max(0, Math.min(display.getVolumeMax(), + display .getVolume() + delta))); + updateDisplay(display); + } + } + + @Override + public void addDisplay(RemoteDisplay display) { + Log.d(TAG, "addDisplay: display=" + display); + super.addDisplay(display); + } + + @Override + public void removeDisplay(RemoteDisplay display) { + Log.d(TAG, "removeDisplay: display=" + display); + super.removeDisplay(display); + } + + @Override + public void updateDisplay(RemoteDisplay display) { + Log.d(TAG, "updateDisplay: display=" + display); + super.updateDisplay(display); + } + + private final Runnable mBlink = new Runnable() { + @Override + public void run() { + if (mTestDisplay7 == null) { + if (mBlinking) { + mTestDisplay7 = new RemoteDisplay("testDisplay7", + "Test Display 7 (blinky)"); + mTestDisplay7.setDescription("Comes and goes but can't connect"); + mTestDisplay7.setStatus(RemoteDisplay.STATUS_AVAILABLE); + addDisplay(mTestDisplay7); + mHandler.postDelayed(this, 7000); + } + } else { + removeDisplay(mTestDisplay7); + mTestDisplay7 = null; + if (mBlinking) { + mHandler.postDelayed(this, 4000); + } + } + } + }; + } +} diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java index e4c4214..df32ee1 100644 --- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java @@ -93,7 +93,7 @@ public class WindowManagerPermissionTests extends TestCase { } try { - mWm.addAppToken(0, null, 0, 0, 0, false, false, 0); + mWm.addAppToken(0, null, 0, 0, 0, false, false, 0, 0); fail("IWindowManager.addAppToken did not throw SecurityException as" + " expected"); } catch (SecurityException e) { diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk index 4e73568..ed497a5 100644 --- a/tools/layoutlib/Android.mk +++ b/tools/layoutlib/Android.mk @@ -31,6 +31,9 @@ built_framework_classes := $(call java-lib-files,framework-base) built_core_dep := $(call java-lib-deps,core) built_core_classes := $(call java-lib-files,core) +built_ext_dep := $(call java-lib-deps,ext) +built_ext_classes := $(call java-lib-files,ext) + built_layoutlib_create_jar := $(call intermediates-dir-for, \ JAVA_LIBRARIES,layoutlib_create,HOST)/javalib.jar @@ -47,6 +50,7 @@ include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(built_core_dep) \ $(built_framework_dep) \ + $(built_ext_dep) \ $(built_layoutlib_create_jar) $(hide) echo "host layoutlib_create: $@" $(hide) mkdir -p $(dir $@) @@ -55,7 +59,8 @@ $(LOCAL_BUILT_MODULE): $(built_core_dep) \ $(hide) java -jar $(built_layoutlib_create_jar) \ $@ \ $(built_core_classes) \ - $(built_framework_classes) + $(built_framework_classes) \ + $(built_ext_classes) $(hide) ls -l $(built_framework_classes) diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java index ec284ac..93284db 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java @@ -308,8 +308,9 @@ public final class Bitmap_Delegate { } @LayoutlibDelegate - /*package*/ static void nativeRecycle(int nativeBitmap) { + /*package*/ static boolean nativeRecycle(int nativeBitmap) { sManager.removeJavaReferenceFor(nativeBitmap); + return true; } @LayoutlibDelegate diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index fd153af..dd2cbc1 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -81,7 +81,7 @@ public class IWindowManagerImpl implements IWindowManager { @Override public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, int arg4, - boolean arg5, boolean arg6, int arg7) + boolean arg5, boolean arg6, int arg7, int arg8) throws RemoteException { // TODO Auto-generated method stub diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java index 17b0eb6..bcd08eb4 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java @@ -290,7 +290,7 @@ abstract class CustomBar extends LinearLayout { TypedValue out = new TypedValue(); if (ResourceHelper.parseFloatAttribute("textSize", textSize.getValue(), out, true /*requireUnit*/)) { - textView.setTextSize( + textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, out.getDimension(bridgeContext.getResources().getDisplayMetrics())); } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java index 23d08e3..60f5331 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java @@ -273,7 +273,6 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso mContext.getRenderResources().setLogger(null); } - mContext = null; } public static BridgeContext getCurrentContext() { diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java index 06ae804..ad4103b 100644 --- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java +++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java @@ -46,7 +46,7 @@ public class ICU_Delegate { // --- Native methods accessing ICU's database. @LayoutlibDelegate - /*package*/ static String getBestDateTimePattern(String skeleton, String localeName) { + /*package*/ static String getBestDateTimePatternNative(String skeleton, String localeName) { return DateTimePatternGenerator.getInstance(new ULocale(localeName)) .getBestPattern(skeleton); } @@ -167,7 +167,7 @@ public class ICU_Delegate { } @LayoutlibDelegate - /*package*/ static boolean initLocaleDataImpl(String locale, LocaleData result) { + /*package*/ static boolean initLocaleDataNative(String locale, LocaleData result) { // Used by Calendar. result.firstDayOfWeek = Integer.valueOf(1); diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java index ba23048..ee501d2 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java @@ -113,6 +113,7 @@ public class Main { "android.pim.*", // for datepicker "android.os.*", // for android.os.Handler "android.database.ContentObserver", // for Digital clock + "com.android.i18n.phonenumbers.*", // for TextView with autolink attribute }, excludeClasses); aa.analyze(); diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 5a1928c..149bda6 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -117,7 +117,7 @@ interface IWifiManager void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable); - boolean requestBatchedScan(in BatchedScanSettings requested, IBinder binder); + boolean requestBatchedScan(in BatchedScanSettings requested, IBinder binder, in WorkSource ws); void stopBatchedScan(in BatchedScanSettings requested); diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java index f6a621f..e76eb17 100644 --- a/wifi/java/android/net/wifi/SupplicantStateTracker.java +++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java @@ -55,7 +55,7 @@ class SupplicantStateTracker extends StateMachine { private static final int MAX_RETRIES_ON_AUTHENTICATION_FAILURE = 2; /* Maximum retries on assoc rejection events */ - private static final int MAX_RETRIES_ON_ASSOCIATION_REJECT = 4; + private static final int MAX_RETRIES_ON_ASSOCIATION_REJECT = 16; /* Tracks if networks have been disabled during a connection */ private boolean mNetworksDisabledDuringConnect = false; diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 7fc8bef..3b47e63 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -799,7 +799,13 @@ public class WifiManager { */ public boolean requestBatchedScan(BatchedScanSettings requested) { try { - return mService.requestBatchedScan(requested, new Binder()); + return mService.requestBatchedScan(requested, new Binder(), null); + } catch (RemoteException e) { return false; } + } + /** @hide */ + public boolean requestBatchedScan(BatchedScanSettings requested, WorkSource workSource) { + try { + return mService.requestBatchedScan(requested, new Binder(), workSource); } catch (RemoteException e) { return false; } } diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java index 520668e..c2f278a 100644 --- a/wifi/java/android/net/wifi/WifiNative.java +++ b/wifi/java/android/net/wifi/WifiNative.java @@ -39,7 +39,6 @@ import java.util.Locale; public class WifiNative { private static final boolean DBG = false; - private static final boolean VDBG = false; private final String mTAG; private static final int DEFAULT_GROUP_OWNER_INTENT = 6; @@ -118,12 +117,12 @@ public class WifiNative { public boolean connectToSupplicant() { // No synchronization necessary .. it is implemented in WifiMonitor - if (VDBG) localLog(mInterfacePrefix + "connectToSupplicant"); + localLog(mInterfacePrefix + "connectToSupplicant"); return connectToSupplicantNative(); } public void closeSupplicantConnection() { - if (VDBG) localLog(mInterfacePrefix + "closeSupplicantConnection"); + localLog(mInterfacePrefix + "closeSupplicantConnection"); closeSupplicantConnectionNative(); } @@ -136,9 +135,9 @@ public class WifiNative { if (DBG) Log.d(mTAG, "doBoolean: " + command); synchronized (mLock) { int cmdId = getNewCmdIdLocked(); - if (VDBG) localLog(cmdId + "->" + mInterfacePrefix + command); + localLog(cmdId + "->" + mInterfacePrefix + command); boolean result = doBooleanCommandNative(mInterfacePrefix + command); - if (VDBG) localLog(cmdId + "<-" + result); + localLog(cmdId + "<-" + result); if (DBG) Log.d(mTAG, " returned " + result); return result; } @@ -148,9 +147,9 @@ public class WifiNative { if (DBG) Log.d(mTAG, "doInt: " + command); synchronized (mLock) { int cmdId = getNewCmdIdLocked(); - if (VDBG) localLog(cmdId + "->" + mInterfacePrefix + command); + localLog(cmdId + "->" + mInterfacePrefix + command); int result = doIntCommandNative(mInterfacePrefix + command); - if (VDBG) localLog(cmdId + "<-" + result); + localLog(cmdId + "<-" + result); if (DBG) Log.d(mTAG, " returned " + result); return result; } @@ -160,9 +159,9 @@ public class WifiNative { if (DBG) Log.d(mTAG, "doString: " + command); synchronized (mLock) { int cmdId = getNewCmdIdLocked(); - if (VDBG) localLog(cmdId + "->" + mInterfacePrefix + command); + localLog(cmdId + "->" + mInterfacePrefix + command); String result = doStringCommandNative(mInterfacePrefix + command); - if (VDBG) localLog(cmdId + "<-" + result); + localLog(cmdId + "<-" + result); if (DBG) Log.d(mTAG, " returned " + result); return result; } @@ -298,7 +297,9 @@ public class WifiNative { * the firmware can remember before it runs out of buffer space or -1 on error */ public String setBatchedScanSettings(BatchedScanSettings settings) { - if (settings == null) return doStringCommand("DRIVER WLS_BATCHING STOP"); + if (settings == null) { + return doStringCommand("DRIVER WLS_BATCHING STOP"); + } String cmd = "DRIVER WLS_BATCHING SET SCANFREQ=" + settings.scanIntervalSec; cmd += " MSCAN=" + settings.maxScansPerBatch; if (settings.maxApPerScan != BatchedScanSettings.UNSPECIFIED) { diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 78da7e7..eedd66f 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -57,6 +57,7 @@ import android.net.wifi.p2p.WifiP2pManager; import android.net.wifi.p2p.WifiP2pService; import android.os.BatteryStats; import android.os.Binder; +import android.os.Bundle; import android.os.IBinder; import android.os.INetworkManagementService; import android.os.Message; @@ -416,7 +417,8 @@ public class WifiStateMachine extends StateMachine { /* change the batch scan settings. * arg1 = responsible UID - * obj = the new settings + * arg2 = csph (channel scans per hour) + * obj = bundle with the new settings and the optional worksource */ public static final int CMD_SET_BATCHED_SCAN = BASE + 135; public static final int CMD_START_NEXT_BATCHED_SCAN = BASE + 136; @@ -628,6 +630,15 @@ public class WifiStateMachine extends StateMachine { private BatchedScanSettings mBatchedScanSettings = null; + /** + * Track the worksource/cost of the current settings and track what's been noted + * to the battery stats, so we can mark the end of the previous when changing. + */ + private WorkSource mBatchedScanWorkSource = null; + private int mBatchedScanCsph = 0; + private WorkSource mNotedBatchedScanWorkSource = null; + private int mNotedBatchedScanCsph = 0; + public WifiStateMachine(Context context, String wlanInterface) { super("WifiStateMachine"); @@ -841,8 +852,14 @@ public class WifiStateMachine extends StateMachine { /** * start or stop batched scanning using the given settings */ - public void setBatchedScanSettings(BatchedScanSettings settings, int callingUid) { - sendMessage(CMD_SET_BATCHED_SCAN, callingUid, 0, settings); + private static final String BATCHED_SETTING = "batched_settings"; + private static final String BATCHED_WORKSOURCE = "batched_worksource"; + public void setBatchedScanSettings(BatchedScanSettings settings, int callingUid, int csph, + WorkSource workSource) { + Bundle bundle = new Bundle(); + bundle.putParcelable(BATCHED_SETTING, settings); + bundle.putParcelable(BATCHED_WORKSOURCE, workSource); + sendMessage(CMD_SET_BATCHED_SCAN, callingUid, csph, bundle); } public List<BatchedScanResult> syncGetBatchedScanResultsList() { @@ -861,6 +878,8 @@ public class WifiStateMachine extends StateMachine { } private void startBatchedScan() { + if (mBatchedScanSettings == null) return; + if (mDhcpActive) { if (DBG) log("not starting Batched Scans due to DHCP"); return; @@ -872,10 +891,10 @@ public class WifiStateMachine extends StateMachine { mAlarmManager.cancel(mBatchedScanIntervalIntent); String scansExpected = mWifiNative.setBatchedScanSettings(mBatchedScanSettings); - try { mExpectedBatchedScans = Integer.parseInt(scansExpected); setNextBatchedAlarm(mExpectedBatchedScans); + if (mExpectedBatchedScans > 0) noteBatchedScanStart(); } catch (NumberFormatException e) { stopBatchedScan(); loge("Exception parsing WifiNative.setBatchedScanSettings response " + e); @@ -918,25 +937,31 @@ public class WifiStateMachine extends StateMachine { } // return true if new/different - private boolean recordBatchedScanSettings(BatchedScanSettings settings) { - if (DBG) log("set batched scan to " + settings); + private boolean recordBatchedScanSettings(int responsibleUid, int csph, Bundle bundle) { + BatchedScanSettings settings = bundle.getParcelable(BATCHED_SETTING); + WorkSource responsibleWorkSource = bundle.getParcelable(BATCHED_WORKSOURCE); + + if (DBG) { + log("set batched scan to " + settings + " for uid=" + responsibleUid + + ", worksource=" + responsibleWorkSource); + } if (settings != null) { - // TODO - noteBatchedScanStart(message.arg1); if (settings.equals(mBatchedScanSettings)) return false; } else { if (mBatchedScanSettings == null) return false; - // TODO - noteBatchedScanStop(message.arg1); } mBatchedScanSettings = settings; + if (responsibleWorkSource == null) responsibleWorkSource = new WorkSource(responsibleUid); + mBatchedScanWorkSource = responsibleWorkSource; + mBatchedScanCsph = csph; return true; } private void stopBatchedScan() { mAlarmManager.cancel(mBatchedScanIntervalIntent); - if (mBatchedScanSettings != null) { - retrieveBatchedScanData(); - mWifiNative.setBatchedScanSettings(null); - } + retrieveBatchedScanData(); + mWifiNative.setBatchedScanSettings(null); + noteBatchedScanStop(); } private void setNextBatchedAlarm(int scansExpected) { @@ -1164,6 +1189,44 @@ public class WifiStateMachine extends StateMachine { } } + private void noteBatchedScanStart() { + // note the end of a previous scan set + if (mNotedBatchedScanWorkSource != null && + (mNotedBatchedScanWorkSource.equals(mBatchedScanWorkSource) == false || + mNotedBatchedScanCsph != mBatchedScanCsph)) { + try { + mBatteryStats.noteWifiBatchedScanStoppedFromSource(mNotedBatchedScanWorkSource); + } catch (RemoteException e) { + log(e.toString()); + } finally { + mNotedBatchedScanWorkSource = null; + mNotedBatchedScanCsph = 0; + } + } + // note the start of the new + try { + mBatteryStats.noteWifiBatchedScanStartedFromSource(mBatchedScanWorkSource, + mBatchedScanCsph); + mNotedBatchedScanWorkSource = mBatchedScanWorkSource; + mNotedBatchedScanCsph = mBatchedScanCsph; + } catch (RemoteException e) { + log(e.toString()); + } + } + + private void noteBatchedScanStop() { + if (mNotedBatchedScanWorkSource != null) { + try { + mBatteryStats.noteWifiBatchedScanStoppedFromSource(mNotedBatchedScanWorkSource); + } catch (RemoteException e) { + log(e.toString()); + } finally { + mNotedBatchedScanWorkSource = null; + mNotedBatchedScanCsph = 0; + } + } + } + private void startScanNative(int type) { mWifiNative.scan(type); mScanResultIsPending = true; @@ -1868,6 +1931,9 @@ public class WifiStateMachine extends StateMachine { return; } + // note that all these splits and substrings keep references to the original + // huge string buffer while the amount we really want is generally pretty small + // so make copies instead (one example b/11087956 wasted 400k of heap here). synchronized(mScanResultCache) { mScanResults = new ArrayList<ScanResult>(); String[] lines = scanResults.split("\n"); @@ -2307,9 +2373,7 @@ public class WifiStateMachine extends StateMachine { mDhcpActive = false; - if (mBatchedScanSettings != null) { - startBatchedScan(); - } + startBatchedScan(); } private void handleSuccessfulIpConfiguration(DhcpResults dhcpResults) { @@ -2447,7 +2511,7 @@ public class WifiStateMachine extends StateMachine { } break; case CMD_SET_BATCHED_SCAN: - recordBatchedScanSettings((BatchedScanSettings)message.obj); + recordBatchedScanSettings(message.arg1, message.arg2, (Bundle)message.obj); break; case CMD_POLL_BATCHED_SCAN: handleBatchedScanPollRequest(); @@ -2960,9 +3024,7 @@ public class WifiStateMachine extends StateMachine { mDhcpActive = false; - if (mBatchedScanSettings != null) { - startBatchedScan(); - } + startBatchedScan(); if (mOperationalMode != CONNECT_MODE) { mWifiNative.disconnect(); @@ -3021,8 +3083,10 @@ public class WifiStateMachine extends StateMachine { startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP); break; case CMD_SET_BATCHED_SCAN: - recordBatchedScanSettings((BatchedScanSettings)message.obj); - startBatchedScan(); + if (recordBatchedScanSettings(message.arg1, message.arg2, + (Bundle)message.obj)) { + startBatchedScan(); + } break; case CMD_SET_COUNTRY_CODE: String country = (String) message.obj; @@ -3160,9 +3224,7 @@ public class WifiStateMachine extends StateMachine { updateBatteryWorkSource(null); mScanResults = new ArrayList<ScanResult>(); - if (mBatchedScanSettings != null) { - stopBatchedScan(); - } + stopBatchedScan(); final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); |
