diff options
Diffstat (limited to 'core')
107 files changed, 2595 insertions, 1213 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index f49005e..cb1e903 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3250,8 +3250,21 @@ public final class ActivityThread { r.window = null; r.hideForNow = false; r.nextIdle = null; - r.pendingResults = tmp.pendingResults; - r.pendingIntents = tmp.pendingIntents; + // Merge any pending results and pending intents; don't just replace them + if (tmp.pendingResults != null) { + if (r.pendingResults == null) { + r.pendingResults = tmp.pendingResults; + } else { + r.pendingResults.addAll(tmp.pendingResults); + } + } + if (tmp.pendingIntents != null) { + if (r.pendingIntents == null) { + r.pendingIntents = tmp.pendingIntents; + } else { + r.pendingIntents.addAll(tmp.pendingIntents); + } + } r.startsNotResumed = tmp.startsNotResumed; if (savedState != null) { r.state = savedState; diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java index 3b5ad86..ecef38f 100644 --- a/core/java/android/app/ApplicationContext.java +++ b/core/java/android/app/ApplicationContext.java @@ -103,6 +103,9 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.WeakHashMap; +import java.util.Set; +import java.util.HashSet; import java.util.Map.Entry; import org.xmlpull.v1.XmlPullParserException; @@ -2476,7 +2479,8 @@ class ApplicationContext extends Context { private final FileStatus mFileStatus = new FileStatus(); private long mTimestamp; - private List<OnSharedPreferenceChangeListener> mListeners; + private static final Object mContent = new Object(); + private WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners; SharedPreferencesImpl( File file, int mode, Map initialContents) { @@ -2487,7 +2491,7 @@ class ApplicationContext extends Context { if (FileUtils.getFileStatus(file.getPath(), mFileStatus)) { mTimestamp = mFileStatus.mtime; } - mListeners = new ArrayList<OnSharedPreferenceChangeListener>(); + mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>(); } public boolean hasFileChanged() { @@ -2509,9 +2513,7 @@ class ApplicationContext extends Context { public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { synchronized(this) { - if (!mListeners.contains(listener)) { - mListeners.add(listener); - } + mListeners.put(listener, mContent); } } @@ -2620,13 +2622,14 @@ class ApplicationContext extends Context { boolean hasListeners; List<String> keysModified = null; - List<OnSharedPreferenceChangeListener> listeners = null; + Set<OnSharedPreferenceChangeListener> listeners = null; synchronized (SharedPreferencesImpl.this) { hasListeners = mListeners.size() > 0; if (hasListeners) { keysModified = new ArrayList<String>(); - listeners = new ArrayList<OnSharedPreferenceChangeListener>(mListeners); + listeners = + new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet()); } synchronized (this) { @@ -2635,9 +2638,7 @@ class ApplicationContext extends Context { mClear = false; } - Iterator<Entry<String, Object>> it = mModified.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry<String, Object> e = it.next(); + for (Entry<String, Object> e : mModified.entrySet()) { String k = e.getKey(); Object v = e.getValue(); if (v == this) { @@ -2660,10 +2661,10 @@ class ApplicationContext extends Context { if (hasListeners) { for (int i = keysModified.size() - 1; i >= 0; i--) { final String key = keysModified.get(i); - // Call in the order they were registered - final int listenersSize = listeners.size(); - for (int j = 0; j < listenersSize; j++) { - listeners.get(j).onSharedPreferenceChanged(SharedPreferencesImpl.this, key); + for (OnSharedPreferenceChangeListener listener : listeners) { + if (listener != null) { + listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key); + } } } } diff --git a/core/java/android/app/LauncherActivity.java b/core/java/android/app/LauncherActivity.java index d6fcbb1..8d249da 100644 --- a/core/java/android/app/LauncherActivity.java +++ b/core/java/android/app/LauncherActivity.java @@ -65,6 +65,7 @@ public abstract class LauncherActivity extends ListActivity { public Drawable icon; public String packageName; public String className; + public Bundle extras; ListItem(PackageManager pm, ResolveInfo resolveInfo, IconResizer resizer) { label = resolveInfo.loadLabel(pm); @@ -115,6 +116,9 @@ public abstract class LauncherActivity extends ListActivity { Intent intent = new Intent(mIntent); ListItem item = mActivitiesList.get(position); intent.setClassName(item.packageName, item.className); + if (item.extras != null) { + intent.putExtras(item.extras); + } return intent; } diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java index a6a436f..d2fb605 100644 --- a/core/java/android/app/Service.java +++ b/core/java/android/app/Service.java @@ -278,11 +278,11 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac } /** - * Stop the service, if the most recent time it was started was + * Stop the service if the most recent time it was started was * <var>startId</var>. This is the same as calling {@link * android.content.Context#stopService} for this particular service but allows you to * safely avoid stopping if there is a start request from a client that you - * haven't yet see in {@link #onStart}. + * haven't yet seen in {@link #onStart}. * * @param startId The most recent start identifier received in {@link * #onStart}. diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index 3b10ed2..eca04b3 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -109,6 +109,23 @@ public class AppWidgetManager { public static final String EXTRA_APPWIDGET_IDS = "appWidgetIds"; /** + * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of + * {@link AppWidgetProviderInfo} objects to mix in to the list of AppWidgets that are + * installed. (This is how the launcher shows the search widget). + */ + public static final String EXTRA_CUSTOM_INFO = "customInfo"; + + /** + * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of + * {@link android.os.Bundle} objects to mix in to the list of AppWidgets that are + * installed. It will be added to the extras object on the {@link android.content.Intent} + * that is returned from the picker activity. + * + * {@more} + */ + public static final String EXTRA_CUSTOM_EXTRAS = "customExtras"; + + /** * A sentiel value that the AppWidget manager will never return as a appWidgetId. */ public static final int INVALID_APPWIDGET_ID = 0; diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 1ba1c1e..abf08cb 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -31,6 +31,12 @@ import java.io.UnsupportedEncodingException; * @hide */ public class BluetoothDevice { + + public static final int BLUETOOTH_STATE_OFF = 0; + public static final int BLUETOOTH_STATE_TURNING_ON = 1; + public static final int BLUETOOTH_STATE_ON = 2; + public static final int BLUETOOTH_STATE_TURNING_OFF = 3; + /** Inquiry scan and page scan are both off. * Device is neither discoverable nor connectable */ public static final int SCAN_MODE_NONE = 0; @@ -83,7 +89,7 @@ public class BluetoothDevice { } /** - * Get the current status of Bluetooth hardware. + * Is Bluetooth currently turned on. * * @return true if Bluetooth enabled, false otherwise. */ @@ -95,37 +101,30 @@ public class BluetoothDevice { } /** + * Get the current state of Bluetooth. + * + * @return One of BLUETOOTH_STATE_ or BluetoothError.ERROR. + */ + public int getBluetoothState() { + try { + return mService.getBluetoothState(); + } catch (RemoteException e) {Log.e(TAG, "", e);} + return BluetoothError.ERROR; + } + + /** * Enable the Bluetooth device. * Turn on the underlying hardware. - * This is an asynchronous call, BluetoothIntent.ENABLED_ACTION will be - * sent if and when the device is successfully enabled. + * This is an asynchronous call, + * BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION can be used to check if + * and when the device is sucessfully enabled. * @return false if we cannot enable the Bluetooth device. True does not * imply the device was enabled, it only implies that so far there were no * problems. */ public boolean enable() { - return enable(null); - } - - /** - * Enable the Bluetooth device. - * Turns on the underlying hardware. - * This is an asynchronous call. onEnableResult() of your callback will be - * called when the call is complete, with either RESULT_SUCCESS or - * RESULT_FAILURE. - * - * Your callback will be called from a binder thread, not the main thread. - * - * In addition to the callback, BluetoothIntent.ENABLED_ACTION will be - * broadcast if the device is successfully enabled. - * - * @param callback Your callback, null is ok. - * @return true if your callback was successfully registered, or false if - * there was an error, implying your callback will never be called. - */ - public boolean enable(IBluetoothDeviceCallback callback) { try { - return mService.enable(callback); + return mService.enable(); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; } @@ -138,7 +137,7 @@ public class BluetoothDevice { */ public boolean disable() { try { - return mService.disable(); + return mService.disable(true); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; } @@ -551,7 +550,6 @@ public class BluetoothDevice { } return pinBytes; } - private static final int ADDRESS_LENGTH = 17; /** Sanity check a bluetooth address, such as "00:43:A8:23:10:F0" */ diff --git a/core/java/android/bluetooth/BluetoothIntent.java b/core/java/android/bluetooth/BluetoothIntent.java index 9273d0d..344601b 100644 --- a/core/java/android/bluetooth/BluetoothIntent.java +++ b/core/java/android/bluetooth/BluetoothIntent.java @@ -41,6 +41,10 @@ public interface BluetoothIntent { "android.bluetooth.intent.RSSI"; public static final String CLASS = "android.bluetooth.intent.CLASS"; + public static final String BLUETOOTH_STATE = + "android.bluetooth.intent.BLUETOOTH_STATE"; + public static final String BLUETOOTH_PREVIOUS_STATE = + "android.bluetooth.intent.BLUETOOTH_PREVIOUS_STATE"; public static final String HEADSET_STATE = "android.bluetooth.intent.HEADSET_STATE"; public static final String HEADSET_PREVIOUS_STATE = @@ -54,12 +58,12 @@ public interface BluetoothIntent { public static final String REASON = "android.bluetooth.intent.REASON"; + /** Broadcast when the local Bluetooth device state changes, for example + * when Bluetooth is enabled. Will contain int extra's BLUETOOTH_STATE and + * BLUETOOTH_PREVIOUS_STATE. */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ENABLED_ACTION = - "android.bluetooth.intent.action.ENABLED"; - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String DISABLED_ACTION = - "android.bluetooth.intent.action.DISABLED"; + public static final String BLUETOOTH_STATE_CHANGED_ACTION = + "android.bluetooth.intent.action.BLUETOOTH_STATE_CHANGED"; @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String NAME_CHANGED_ACTION = diff --git a/core/java/android/bluetooth/IBluetoothDevice.aidl b/core/java/android/bluetooth/IBluetoothDevice.aidl index 4351d2e..6cd792e 100644 --- a/core/java/android/bluetooth/IBluetoothDevice.aidl +++ b/core/java/android/bluetooth/IBluetoothDevice.aidl @@ -26,8 +26,9 @@ import android.bluetooth.IBluetoothDeviceCallback; interface IBluetoothDevice { boolean isEnabled(); - boolean enable(in IBluetoothDeviceCallback callback); // async - boolean disable(); + int getBluetoothState(); + boolean enable(); + boolean disable(boolean persistSetting); String getAddress(); String getName(); diff --git a/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl b/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl index d25bd56..d057093 100644 --- a/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl +++ b/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl @@ -22,6 +22,4 @@ package android.bluetooth; oneway interface IBluetoothDeviceCallback { void onGetRemoteServiceChannelResult(in String address, int channel); - - void onEnableResult(int result); } diff --git a/core/java/android/bluetooth/ScoSocket.java b/core/java/android/bluetooth/ScoSocket.java index a43a08b..1bf786f 100644 --- a/core/java/android/bluetooth/ScoSocket.java +++ b/core/java/android/bluetooth/ScoSocket.java @@ -76,7 +76,7 @@ public class ScoSocket { try { if (VDBG) log(this + " SCO OBJECT DTOR"); destroyNative(); - releaseWakeLock(); + releaseWakeLockNow(); } finally { super.finalize(); } @@ -98,7 +98,7 @@ public class ScoSocket { return true; } else { mState = STATE_CLOSED; - releaseWakeLock(); + releaseWakeLockNow(); return false; } } @@ -148,7 +148,7 @@ public class ScoSocket { mState = STATE_CLOSED; } mHandler.obtainMessage(mConnectedCode, mState, -1, this).sendToTarget(); - releaseWakeLock(); + releaseWakeLockNow(); } private synchronized void onAccepted(int result) { @@ -183,7 +183,19 @@ public class ScoSocket { private void releaseWakeLock() { if (mWakeLock.isHeld()) { - if (VDBG) log("mWakeLock.release() " + this); + // Keep apps processor awake for a further 2 seconds. + // This is a hack to resolve issue http://b/1616263 - in which + // we are left in a 80 mA power state when remotely terminating a + // call while connected to BT headset "HTC BH S100 " with A2DP and + // HFP profiles. + if (VDBG) log("mWakeLock.release() in 2 sec" + this); + mWakeLock.acquire(2000); + } + } + + private void releaseWakeLockNow() { + if (mWakeLock.isHeld()) { + if (VDBG) log("mWakeLock.release() now" + this); mWakeLock.release(); } } diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java index 08f6191..a41627a 100644 --- a/core/java/android/content/BroadcastReceiver.java +++ b/core/java/android/content/BroadcastReceiver.java @@ -68,7 +68,7 @@ import android.util.Log; * these broadcasts, the Intent broadcast mechanism here is completely separate * from Intents that are used to start Activities with * {@link Context#startActivity Context.startActivity()}. - * There is no way for an BroadcastReceiver + * There is no way for a BroadcastReceiver * to see or capture Intents used with startActivity(); likewise, when * you broadcast an Intent, you will never find or start an Activity. * These two operations are semantically very different: starting an @@ -103,7 +103,7 @@ import android.util.Log; * its process before the asynchronous operation completes. * * <p>In particular, you may <i>not</i> show a dialog or bind to a service from - * within an BroadcastReceiver. For the former, you should instead use the + * within a BroadcastReceiver. For the former, you should instead use the * {@link android.app.NotificationManager} API. For the latter, you can * use {@link android.content.Context#startService Context.startService()} to * send a command to the service. @@ -141,7 +141,7 @@ import android.util.Log; * <a name="ProcessLifecycle"></a> * <h3>Process Lifecycle</h3> * - * <p>A process that is currently executing an BroadcastReceiver (that is, + * <p>A process that is currently executing a BroadcastReceiver (that is, * currently running the code in its {@link #onReceive} method) is * considered to be a foreground process and will be kept running by the * system except under cases of extreme memory pressure. @@ -156,7 +156,7 @@ import android.util.Log; * more important processes. * * <p>This means that for longer-running operations you will often use - * a {@link android.app.Service} in conjunction with an BroadcastReceiver to keep + * an {@link android.app.Service} in conjunction with a BroadcastReceiver to keep * the containing process active for the entire time of your operation. */ public abstract class BroadcastReceiver { diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 90ff78a..306c02e 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1035,7 +1035,7 @@ public class Intent implements Parcelable { */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_SEARCH_LONG_PRESS = "android.intent.action.SEARCH_LONG_PRESS"; - + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Standard intent broadcast actions (see action variable). @@ -1052,7 +1052,7 @@ public class Intent implements Parcelable { public static final String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON"; /** - * Broadcast Action: Sent when the user is present after device wakes up (e.g when the + * Broadcast Action: Sent when the user is present after device wakes up (e.g when the * keyguard is gone). */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @@ -1210,7 +1210,7 @@ public class Intent implements Parcelable { /** * Broadcast Action: The charging state, or charge level of the battery has * changed. - * + * * <p class="note"> * You can <em>not</em> receive this through components declared * in manifests, only by exlicitly registering for it with @@ -1380,7 +1380,7 @@ public class Intent implements Parcelable { @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_GTALK_SERVICE_DISCONNECTED = "android.intent.action.GTALK_DISCONNECTED"; - + /** * Broadcast Action: An input method has been changed. * {@hide pending API Council approval} @@ -1450,12 +1450,12 @@ public class Intent implements Parcelable { * * <p>The Intent will have the following extra value: * <ul> - * <li><em>{@link android.content.Intent#EXTRA_PHONE_NUMBER}</em> - + * <li><em>{@link android.content.Intent#EXTRA_PHONE_NUMBER}</em> - * the phone number originally intended to be dialed.</li> * </ul> * <p>Once the broadcast is finished, the resultData is used as the actual * number to call. If <code>null</code>, no call will be placed.</p> - * <p>It is perfectly acceptable for multiple receivers to process the + * <p>It is perfectly acceptable for multiple receivers to process the * outgoing call in turn: for example, a parental control application * might verify that the user is authorized to place the call at that * time, then a number-rewriting application might add an area code if @@ -1463,7 +1463,7 @@ public class Intent implements Parcelable { * <p>For consistency, any receiver whose purpose is to prohibit phone * calls should have a priority of 0, to ensure it will see the final * phone number to be dialed. - * Any receiver whose purpose is to rewrite phone numbers to be called + * Any receiver whose purpose is to rewrite phone numbers to be called * should have a positive priority. * Negative priorities are reserved for the system for this broadcast; * using them may cause problems.</p> @@ -1472,7 +1472,7 @@ public class Intent implements Parcelable { * <p>Emergency calls cannot be intercepted using this mechanism, and * other calls cannot be modified to call emergency numbers using this * mechanism. - * <p>You must hold the + * <p>You must hold the * {@link android.Manifest.permission#PROCESS_OUTGOING_CALLS} * permission to receive this Intent.</p> */ @@ -1709,7 +1709,7 @@ public class Intent implements Parcelable { * implying that this is an update). */ public static final String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED"; - + /** * Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED} * intents to indicate that this is a replacement of the package, so this @@ -1717,7 +1717,7 @@ public class Intent implements Parcelable { * different version of the same package. */ public static final String EXTRA_REPLACING = "android.intent.extra.REPLACING"; - + /** * Used as an int extra field in {@link android.app.AlarmManager} intents * to tell the application being invoked how many pending alarms are being @@ -1728,15 +1728,6 @@ public class Intent implements Parcelable { */ public static final String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT"; - /** - * Used as an int extra field in {@link android.content.Intent#ACTION_VOICE_COMMAND} - * intents to request which audio route the voice command should prefer. - * The value should be a route from {@link android.media.AudioManager}, for - * example ROUTE_BLUETOOTH_SCO. Providing this value is optional. - * {@hide pending API Council approval} - */ - public static final String EXTRA_AUDIO_ROUTE = "android.intent.extra.AUDIO_ROUTE"; - // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Intent flags (see mFlags variable). @@ -1781,7 +1772,7 @@ public class Intent implements Parcelable { * next task activity) defines an atomic group of activities that the * user can move to. Tasks can be moved to the foreground and background; * all of the activities inside of a particular task always remain in - * the same order. See + * the same order. See * <a href="{@docRoot}guide/topics/fundamentals.html#acttask">Application Fundamentals: * Activities and Tasks</a> for more details on tasks. * @@ -1812,7 +1803,7 @@ public class Intent implements Parcelable { * <p><strong>Because the default system does not include graphical task management, * you should not use this flag unless you provide some way for a user to * return back to the tasks you have launched.</strong> - * + * * <p>This flag is ignored if * {@link #FLAG_ACTIVITY_NEW_TASK} is not set. * @@ -1901,7 +1892,7 @@ public class Intent implements Parcelable { * the user re-launching it from home), this activity and all on top of * it will be finished so that the user does not return to them, but * instead returns to whatever activity preceeded it. - * + * * <p>This is useful for cases where you have a logical break in your * application. For example, an e-mail application may have a command * to view an attachment, which launches an image view activity to @@ -1919,31 +1910,31 @@ public class Intent implements Parcelable { * If set, this flag will prevent the normal {@link android.app.Activity#onUserLeaveHint} * callback from occurring on the current frontmost activity before it is * paused as the newly-started activity is brought to the front. - * + * * <p>Typically, an activity can rely on that callback to indicate that an * explicit user action has caused their activity to be moved out of the * foreground. The callback marks an appropriate point in the activity's * lifecycle for it to dismiss any notifications that it intends to display * "until the user has seen them," such as a blinking LED. - * + * * <p>If an activity is ever started via any non-user-driven events such as * phone-call receipt or an alarm handler, this flag should be passed to {@link * Context#startActivity Context.startActivity}, ensuring that the pausing - * activity does not think the user has acknowledged its notification. + * activity does not think the user has acknowledged its notification. */ public static final int FLAG_ACTIVITY_NO_USER_ACTION = 0x00040000; /** * If set in an Intent passed to {@link Context#startActivity Context.startActivity()}, * this flag will cause the launched activity to be brought to the front of its * task's history stack if it is already running. - * + * * <p>For example, consider a task consisting of four activities: A, B, C, D. * If D calls startActivity() with an Intent that resolves to the component * of activity B, then B will be brought to the front of the history stack, * with this resulting order: A, C, D, B. - * + * * This flag will be ignored if {@link #FLAG_ACTIVITY_CLEAR_TOP} is also - * specified. + * specified. */ public static final int FLAG_ACTIVITY_REORDER_TO_FRONT = 0X00020000; /** @@ -1957,11 +1948,11 @@ public class Intent implements Parcelable { * will be launched. Sticky intent state will be recorded properly even * if no receivers wind up being called. If {@link #FLAG_RECEIVER_REGISTERED_ONLY} * is specified in the broadcast intent, this flag is unnecessary. - * + * * <p>This flag is only for use by system sevices as a convenience to * avoid having to implement a more complex mechanism around detection * of boot completion. - * + * * @hide */ public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 0x20000000; @@ -2121,7 +2112,7 @@ public class Intent implements Parcelable { // old format Intent URI if (!uri.startsWith("#Intent;", i)) return getIntentOld(uri); - + // new format Intent intent = new Intent(ACTION_VIEW); @@ -2130,7 +2121,7 @@ public class Intent implements Parcelable { intent.mData = Uri.parse(uri.substring(0, i)); } i += "#Intent;".length(); - + // loop over contents of Intent, all name=value; while (!uri.startsWith("end", i)) { int eq = uri.indexOf('=', i); @@ -2161,7 +2152,7 @@ public class Intent implements Parcelable { else if (uri.startsWith("component=", i)) { intent.mComponent = ComponentName.unflattenFromString(value); } - + // extra else { String key = Uri.decode(uri.substring(i + 2, eq)); @@ -2181,18 +2172,18 @@ public class Intent implements Parcelable { else if (uri.startsWith("s.", i)) b.putShort(key, Short.parseShort(value)); else throw new URISyntaxException(uri, "unknown EXTRA type", i); } - + // move to the next item i = semi + 1; } return intent; - + } catch (IndexOutOfBoundsException e) { throw new URISyntaxException(uri, "illegal Intent URI format", i); } } - + public static Intent getIntentOld(String uri) throws URISyntaxException { Intent intent; @@ -2257,7 +2248,7 @@ public class Intent implements Parcelable { if (uri.regionMatches(i, "extras(", 0, 7)) { i += 7; - + final int closeParen = uri.indexOf(')', i); if (closeParen == -1) throw new URISyntaxException(uri, "EXTRA missing trailing ')'", i); @@ -2272,7 +2263,7 @@ public class Intent implements Parcelable { i++; String key = uri.substring(i, j); i = j + 1; - + // get type-value j = uri.indexOf('!', i); if (j == -1 || j >= closeParen) j = closeParen; @@ -2282,7 +2273,7 @@ public class Intent implements Parcelable { // create Bundle if it doesn't already exist if (intent.mExtras == null) intent.mExtras = new Bundle(); - + // add item to bundle try { switch (type) { @@ -2319,7 +2310,7 @@ public class Intent implements Parcelable { } catch (NumberFormatException e) { throw new URISyntaxException(uri, "EXTRA value can't be parsed", i); } - + char ch = uri.charAt(i); if (ch == ')') break; if (ch != '!') throw new URISyntaxException(uri, "EXTRA missing '!'", i); @@ -2522,7 +2513,7 @@ public class Intent implements Parcelable { public boolean hasFileDescriptors() { return mExtras != null && mExtras.hasFileDescriptors(); } - + /** * Retrieve extended data from the intent. * @@ -3889,7 +3880,7 @@ public class Intent implements Parcelable { /** * Completely replace the extras in the Intent with the extras in the * given Intent. - * + * * @param src The exact extras contained in this Intent are copied * into the target intent, replacing any that were previously there. */ @@ -3897,11 +3888,11 @@ public class Intent implements Parcelable { mExtras = src.mExtras != null ? new Bundle(src.mExtras) : null; return this; } - + /** * Completely replace the extras in the Intent with the given Bundle of * extras. - * + * * @param extras The new set of extras in the Intent, or null to erase * all extras. */ @@ -3909,7 +3900,7 @@ public class Intent implements Parcelable { mExtras = extras != null ? new Bundle(extras) : null; return this; } - + /** * Remove extended data from the intent. * @@ -4397,12 +4388,12 @@ public class Intent implements Parcelable { } } } - + uri.append("end"); return uri.toString(); } - + public int describeContents() { return (mExtras != null) ? mExtras.describeContents() : 0; } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 7287d9c..3e94734 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -341,6 +341,14 @@ public abstract class PackageManager { public static final int INSTALL_FAILED_OLDER_SDK = -12; /** + * Installation return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if + * the new package failed because it contains a content provider with the + * same authority as a provider already installed in the system. + */ + public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13; + + /** * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} * if the parser was given a path that is not a file, or does not end with the expected diff --git a/core/java/android/emoji/EmojiFactory.java b/core/java/android/emoji/EmojiFactory.java index 389bd07..e0b12ae 100644 --- a/core/java/android/emoji/EmojiFactory.java +++ b/core/java/android/emoji/EmojiFactory.java @@ -253,6 +253,22 @@ public final class EmojiFactory { * is returned. */ public static native EmojiFactory newAvailableInstance(); + + /** + * Returns the lowest code point corresponding to an Android + * emoji character. + */ + public int getMinimumAndroidPua() { + return nativeGetMinimumAndroidPua(mNativeEmojiFactory); + } + + /** + * Returns the highest code point corresponding to an Android + * emoji character. + */ + public int getMaximumAndroidPua() { + return nativeGetMaximumAndroidPua(mNativeEmojiFactory); + } // native methods diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 32270c4..6ee92ce 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -22,8 +22,8 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import android.app.Dialog; import android.content.Context; import android.content.res.Configuration; +import android.content.res.TypedArray; import android.graphics.Rect; -import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.IBinder; import android.os.ResultReceiver; @@ -44,6 +44,7 @@ import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.Window; import android.view.WindowManager; +import android.view.animation.AnimationUtils; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; @@ -54,6 +55,8 @@ import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.EditorInfo; import android.widget.Button; import android.widget.FrameLayout; +import android.widget.LinearLayout; + import java.io.FileDescriptor; import java.io.PrintWriter; @@ -204,6 +207,10 @@ import java.io.PrintWriter; * You can use these to reset and initialize your input state for the current * target. For example, you will often want to clear any input state, and * update a soft keyboard to be appropriate for the new inputType.</p> + * + * @attr ref android.R.styleable#InputMethodService_imeFullscreenBackground + * @attr ref android.R.styleable#InputMethodService_imeExtractEnterAnimation + * @attr ref android.R.styleable#InputMethodService_imeExtractExitAnimation */ public class InputMethodService extends AbstractInputMethodService { static final String TAG = "InputMethodService"; @@ -211,13 +218,19 @@ public class InputMethodService extends AbstractInputMethodService { InputMethodManager mImm; + int mTheme = android.R.style.Theme_InputMethod; + LayoutInflater mInflater; + TypedArray mThemeAttrs; View mRootView; SoftInputWindow mWindow; boolean mInitialized; boolean mWindowCreated; boolean mWindowAdded; boolean mWindowVisible; + boolean mWindowWasVisible; + boolean mInShowWindow; + ViewGroup mFullscreenArea; FrameLayout mExtractFrame; FrameLayout mCandidatesFrame; FrameLayout mInputFrame; @@ -243,6 +256,7 @@ public class InputMethodService extends AbstractInputMethodService { boolean mFullscreenApplied; boolean mIsFullscreen; View mExtractView; + boolean mExtractViewHidden; ExtractEditText mExtractEditText; ViewGroup mExtractAccessories; Button mExtractAction; @@ -260,8 +274,8 @@ public class InputMethodService extends AbstractInputMethodService { final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer = new ViewTreeObserver.OnComputeInternalInsetsListener() { public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) { - if (isFullscreenMode()) { - // In fullscreen mode, we just say the window isn't covering + if (isExtractViewShown()) { + // In true fullscreen mode, we just say the window isn't covering // any content so we don't impact whatever is behind. View decor = getWindow().getWindow().getDecorView(); info.contentInsets.top = info.visibleInsets.top @@ -519,12 +533,28 @@ public class InputMethodService extends AbstractInputMethodService { public int touchableInsets; } + /** + * You can call this to customize the theme used by your IME's window. + * This theme should typically be one that derives from + * {@link android.R.style#Theme_InputMethod}, which is the default theme + * you will get. This must be set before {@link #onCreate}, so you + * will typically call it in your constructor with the resource ID + * of your custom theme. + */ + public void setTheme(int theme) { + if (mWindow != null) { + throw new IllegalStateException("Must be called before onCreate()"); + } + mTheme = theme; + } + @Override public void onCreate() { + super.setTheme(mTheme); super.onCreate(); mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE); mInflater = (LayoutInflater)getSystemService( Context.LAYOUT_INFLATER_SERVICE); - mWindow = new SoftInputWindow(this); + mWindow = new SoftInputWindow(this, mTheme); initViews(); mWindow.getWindow().setLayout(FILL_PARENT, WRAP_CONTENT); } @@ -551,6 +581,7 @@ public class InputMethodService extends AbstractInputMethodService { mShowInputRequested = false; mShowInputForced = false; + mThemeAttrs = obtainStyledAttributes(android.R.styleable.InputMethodService); mRootView = mInflater.inflate( com.android.internal.R.layout.input_method, null); mWindow.setContentView(mRootView); @@ -560,6 +591,8 @@ public class InputMethodService extends AbstractInputMethodService { mWindow.getWindow().setWindowAnimations( com.android.internal.R.style.Animation_InputMethodFancy); } + mFullscreenArea = (ViewGroup)mRootView.findViewById(com.android.internal.R.id.fullscreenArea); + mExtractViewHidden = false; mExtractFrame = (FrameLayout)mRootView.findViewById(android.R.id.extractArea); mExtractView = null; mExtractEditText = null; @@ -731,14 +764,20 @@ public class InputMethodService extends AbstractInputMethodService { if (ic != null) ic.reportFullscreenMode(isFullscreen); mFullscreenApplied = true; initialize(); - Drawable bg = onCreateBackgroundDrawable(); - if (bg == null) { - // We need to give the window a real drawable, so that it - // correctly sets its mode. - bg = getResources().getDrawable(android.R.color.transparent); + LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) + mFullscreenArea.getLayoutParams(); + if (isFullscreen) { + mFullscreenArea.setBackgroundDrawable(mThemeAttrs.getDrawable( + com.android.internal.R.styleable.InputMethodService_imeFullscreenBackground)); + lp.height = 0; + lp.weight = 1; + } else { + mFullscreenArea.setBackgroundDrawable(null); + lp.height = LinearLayout.LayoutParams.WRAP_CONTENT; + lp.weight = 0; } - mWindow.getWindow().setBackgroundDrawable(bg); - mExtractFrame.setVisibility(isFullscreen ? View.VISIBLE : View.GONE); + ((ViewGroup)mFullscreenArea.getParent()).updateViewLayout( + mFullscreenArea, lp); if (isFullscreen) { if (mExtractView == null) { View v = onCreateExtractTextView(); @@ -748,6 +787,7 @@ public class InputMethodService extends AbstractInputMethodService { } startExtractingText(false); } + updateExtractFrameVisibility(); } if (changed) { @@ -805,12 +845,66 @@ public class InputMethodService extends AbstractInputMethodService { } /** + * Controls the visibility of the extracted text area. This only applies + * when the input method is in fullscreen mode, and thus showing extracted + * text. When false, the extracted text will not be shown, allowing some + * of the application to be seen behind. This is normally set for you + * by {@link #onUpdateExtractingVisibility}. This controls the visibility + * of both the extracted text and candidate view; the latter since it is + * not useful if there is no text to see. + */ + public void setExtractViewShown(boolean shown) { + if (mExtractViewHidden == shown) { + mExtractViewHidden = !shown; + updateExtractFrameVisibility(); + } + } + + /** + * Return whether the fullscreen extract view is shown. This will only + * return true if {@link #isFullscreenMode()} returns true, and in that + * case its value depends on the last call to + * {@link #setExtractViewShown(boolean)}. This effectively lets you + * determine if the application window is entirely covered (when this + * returns true) or if some part of it may be shown (if this returns + * false, though if {@link #isFullscreenMode()} returns true in that case + * then it is probably only a sliver of the application). + */ + public boolean isExtractViewShown() { + return mIsFullscreen && !mExtractViewHidden; + } + + void updateExtractFrameVisibility() { + int vis; + if (isFullscreenMode()) { + vis = mExtractViewHidden ? View.INVISIBLE : View.VISIBLE; + mExtractFrame.setVisibility(View.VISIBLE); + } else { + vis = View.VISIBLE; + mExtractFrame.setVisibility(View.GONE); + } + updateCandidatesVisibility(mCandidatesVisibility == View.VISIBLE); + if (mWindowWasVisible && mFullscreenArea.getVisibility() != vis) { + int animRes = mThemeAttrs.getResourceId(vis == View.VISIBLE + ? com.android.internal.R.styleable.InputMethodService_imeExtractEnterAnimation + : com.android.internal.R.styleable.InputMethodService_imeExtractExitAnimation, + 0); + if (animRes != 0) { + mFullscreenArea.startAnimation(AnimationUtils.loadAnimation( + this, animRes)); + } + } + mFullscreenArea.setVisibility(vis); + } + + /** * Compute the interesting insets into your UI. The default implementation * uses the top of the candidates frame for the visible insets, and the * top of the input frame for the content insets. The default touchable * insets are {@link Insets#TOUCHABLE_INSETS_VISIBLE}. * - * <p>Note that this method is not called when in fullscreen mode, since + * <p>Note that this method is not called when + * {@link #isExtractViewShown} returns true, since * in that case the application is left as-is behind the input method and * not impacted by anything in its UI. * @@ -821,9 +915,16 @@ public class InputMethodService extends AbstractInputMethodService { if (mInputFrame.getVisibility() == View.VISIBLE) { mInputFrame.getLocationInWindow(loc); } else { - loc[1] = 0; + View decor = getWindow().getWindow().getDecorView(); + loc[1] = decor.getHeight(); + } + if (isFullscreenMode()) { + // In fullscreen mode, we never resize the underlying window. + View decor = getWindow().getWindow().getDecorView(); + outInsets.contentTopInsets = decor.getHeight(); + } else { + outInsets.contentTopInsets = loc[1]; } - outInsets.contentTopInsets = loc[1]; if (mCandidatesFrame.getVisibility() == View.VISIBLE) { mCandidatesFrame.getLocationInWindow(loc); } @@ -889,11 +990,7 @@ public class InputMethodService extends AbstractInputMethodService { * it is hidden. */ public void setCandidatesViewShown(boolean shown) { - int vis = shown ? View.VISIBLE : getCandidatesHiddenVisibility(); - if (mCandidatesVisibility != vis) { - mCandidatesFrame.setVisibility(vis); - mCandidatesVisibility = vis; - } + updateCandidatesVisibility(shown); if (!mShowInputRequested && mWindowVisible != shown) { // If we are being asked to show the candidates view while the app // has not asked for the input view to be shown, then we need @@ -906,17 +1003,26 @@ public class InputMethodService extends AbstractInputMethodService { } } + void updateCandidatesVisibility(boolean shown) { + int vis = shown ? View.VISIBLE : getCandidatesHiddenVisibility(); + if (mCandidatesVisibility != vis) { + mCandidatesFrame.setVisibility(vis); + mCandidatesVisibility = vis; + } + } + /** * Returns the visibility mode (either {@link View#INVISIBLE View.INVISIBLE} * or {@link View#GONE View.GONE}) of the candidates view when it is not - * shown. The default implementation returns GONE when in fullscreen mode, + * shown. The default implementation returns GONE when + * {@link #isExtractViewShown} returns true, * otherwise VISIBLE. Be careful if you change this to return GONE in * other situations -- if showing or hiding the candidates view causes * your window to resize, this can cause temporary drawing artifacts as * the resize takes place. */ public int getCandidatesHiddenVisibility() { - return isFullscreenMode() ? View.GONE : View.INVISIBLE; + return isExtractViewShown() ? View.GONE : View.INVISIBLE; } public void showStatusIcon(int iconResId) { @@ -992,20 +1098,6 @@ public class InputMethodService extends AbstractInputMethodService { } /** - * Called by the framework to create a Drawable for the background of - * the input method window. May return null for no background. The default - * implementation returns a non-null standard background only when in - * fullscreen mode. This is called each time the fullscreen mode changes. - */ - public Drawable onCreateBackgroundDrawable() { - if (isFullscreenMode()) { - return getResources().getDrawable( - com.android.internal.R.drawable.input_method_fullscreen_background); - } - return null; - } - - /** * Called by the framework to create the layout for showing extacted text. * Only called when in fullscreen mode. The returned view hierarchy must * have an {@link ExtractEditText} whose ID is @@ -1174,6 +1266,23 @@ public class InputMethodService extends AbstractInputMethodService { + " mWindowCreated=" + mWindowCreated + " mWindowVisible=" + mWindowVisible + " mInputStarted=" + mInputStarted); + + if (mInShowWindow) { + Log.w(TAG, "Re-entrance in to showWindow"); + return; + } + + try { + mWindowWasVisible = mWindowVisible; + mInShowWindow = true; + showWindowInner(showInput); + } finally { + mWindowWasVisible = true; + mInShowWindow = false; + } + } + + void showWindowInner(boolean showInput) { boolean doShowInput = false; boolean wasVisible = mWindowVisible; mWindowVisible = true; @@ -1241,6 +1350,7 @@ public class InputMethodService extends AbstractInputMethodService { mWindow.hide(); mWindowVisible = false; onWindowHidden(); + mWindowWasVisible = false; } } @@ -1559,7 +1669,7 @@ public class InputMethodService extends AbstractInputMethodService { boolean doMovementKey(int keyCode, KeyEvent event, int count) { final ExtractEditText eet = mExtractEditText; - if (isFullscreenMode() && isInputViewShown() && eet != null) { + if (isExtractViewShown() && isInputViewShown() && eet != null) { // If we are in fullscreen mode, the cursor will move around // the extract edit text, but should NOT cause focus to move // to other fields. @@ -1583,10 +1693,10 @@ public class InputMethodService extends AbstractInputMethodService { if (movement.onKeyOther(eet, (Spannable)eet.getText(), event)) { reportExtractedMovement(keyCode, count); } else { - KeyEvent down = new KeyEvent(event, KeyEvent.ACTION_DOWN); + KeyEvent down = KeyEvent.changeAction(event, KeyEvent.ACTION_DOWN); if (movement.onKeyDown(eet, (Spannable)eet.getText(), keyCode, down)) { - KeyEvent up = new KeyEvent(event, KeyEvent.ACTION_UP); + KeyEvent up = KeyEvent.changeAction(event, KeyEvent.ACTION_UP); movement.onKeyUp(eet, (Spannable)eet.getText(), keyCode, up); while (--count > 0) { @@ -1800,18 +1910,52 @@ public class InputMethodService extends AbstractInputMethodService { } /** - * Called when it is time to update the actions available from a full-screen - * IME. You do not need to deal with this if you are using the standard + * Called when the fullscreen-mode extracting editor info has changed, + * to determine whether the extracting (extract text and candidates) portion + * of the UI should be shown. The standard implementation hides or shows + * the extract area depending on whether it makes sense for the + * current editor. In particular, a {@link InputType#TYPE_NULL} + * input type or {@link EditorInfo#IME_FLAG_NO_EXTRACT_UI} flag will + * turn off the extract area since there is no text to be shown. + */ + public void onUpdateExtractingVisibility(EditorInfo ei) { + if (ei.inputType == InputType.TYPE_NULL || + (ei.imeOptions&EditorInfo.IME_FLAG_NO_EXTRACT_UI) != 0) { + // No reason to show extract UI! + setExtractViewShown(false); + return; + } + + setExtractViewShown(true); + } + + /** + * Called when the fullscreen-mode extracting editor info has changed, + * to update the state of its UI such as the action buttons shown. + * You do not need to deal with this if you are using the standard * full screen extract UI. If replacing it, you will need to re-implement - * this to put the action in your own UI and handle it. + * this to put the appropriate action button in your own UI and handle it, + * and perform any other changes. + * + * <p>The standard implementation turns on or off its accessory area + * depending on whether there is an action button, and hides or shows + * the entire extract area depending on whether it makes sense for the + * current editor. In particular, a {@link InputType#TYPE_NULL} or + * {@link InputType#TYPE_TEXT_VARIATION_FILTER} input type will turn off the + * extract area since there is no text to be shown. */ - public void onUpdateExtractingAccessories(EditorInfo ei) { + public void onUpdateExtractingViews(EditorInfo ei) { + if (!isExtractViewShown()) { + return; + } + if (mExtractAccessories == null) { return; } final boolean hasAction = ei.actionLabel != null || ( (ei.imeOptions&EditorInfo.IME_MASK_ACTION) != EditorInfo.IME_ACTION_NONE && - (ei.imeOptions&EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0); + (ei.imeOptions&EditorInfo.IME_FLAG_NO_ACCESSORY_ACTION) == 0 && + ei.inputType != InputType.TYPE_NULL); if (hasAction) { mExtractAccessories.setVisibility(View.VISIBLE); if (ei.actionLabel != null) { @@ -1855,7 +1999,8 @@ public class InputMethodService extends AbstractInputMethodService { try { eet.startInternalChanges(); - onUpdateExtractingAccessories(ei); + onUpdateExtractingVisibility(ei); + onUpdateExtractingViews(ei); int inputType = ei.inputType; if ((inputType&EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT) { @@ -1890,8 +2035,10 @@ public class InputMethodService extends AbstractInputMethodService { final Printer p = new PrintWriterPrinter(fout); p.println("Input method service state for " + this + ":"); p.println(" mWindowCreated=" + mWindowCreated - + " mWindowAdded=" + mWindowAdded - + " mWindowVisible=" + mWindowVisible); + + " mWindowAdded=" + mWindowAdded); + p.println(" mWindowVisible=" + mWindowVisible + + " mWindowWasVisible=" + mWindowWasVisible + + " mInShowWindow=" + mInShowWindow); p.println(" Configuration=" + getResources().getConfiguration()); p.println(" mToken=" + mToken); p.println(" mInputBinding=" + mInputBinding); @@ -1914,7 +2061,8 @@ public class InputMethodService extends AbstractInputMethodService { + " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags)); p.println(" mCandidatesVisibility=" + mCandidatesVisibility + " mFullscreenApplied=" + mFullscreenApplied - + " mIsFullscreen=" + mIsFullscreen); + + " mIsFullscreen=" + mIsFullscreen + + " mExtractViewHidden=" + mExtractViewHidden); if (mExtractedText != null) { p.println(" mExtractedText:"); diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java index c37845f..d91ace6 100644 --- a/core/java/android/inputmethodservice/SoftInputWindow.java +++ b/core/java/android/inputmethodservice/SoftInputWindow.java @@ -31,18 +31,6 @@ import android.view.WindowManager; */ class SoftInputWindow extends Dialog { - /** - * Create a DockWindow that uses the default style. - * - * @param context The Context the DockWindow is to run it. In particular, it - * uses the window manager and theme in this context to present its - * UI. - */ - public SoftInputWindow(Context context) { - super(context, com.android.internal.R.style.Theme_InputMethod); - initDockWindow(); - } - public void setToken(IBinder token) { WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.token = token; diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 7590bfe..76c74df 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -4,6 +4,8 @@ import java.io.PrintWriter; import java.util.Formatter; import java.util.Map; +import com.android.internal.os.BatteryStatsImpl.Timer; + import android.util.Log; import android.util.Printer; import android.util.SparseArray; @@ -39,6 +41,20 @@ public abstract class BatteryStats implements Parcelable { * {@hide} */ public static final int SENSOR = 3; + + /** + * A constant indicating a full wifi lock timer + * + * {@hide} + */ + public static final int FULL_WIFI_LOCK = 4; + + /** + * A constant indicating a scan wifi lock timer + * + * {@hide} + */ + public static final int SCAN_WIFI_LOCK = 5; /** * Include all of the data in the stats, including previously saved data. @@ -74,6 +90,7 @@ public abstract class BatteryStats implements Parcelable { private static final String WAKELOCK_DATA = "wakelock"; private static final String NETWORK_DATA = "network"; private static final String BATTERY_DATA = "battery"; + private static final String WIFI_LOCK_DATA = "wifilock"; private static final String MISC_DATA = "misc"; private final StringBuilder mFormatBuilder = new StringBuilder(8); @@ -162,6 +179,13 @@ public abstract class BatteryStats implements Parcelable { * {@hide} */ public abstract long getTcpBytesSent(int which); + + public abstract void noteFullWifiLockAcquiredLocked(); + public abstract void noteFullWifiLockReleasedLocked(); + public abstract void noteScanWifiLockAcquiredLocked(); + public abstract void noteScanWifiLockReleasedLocked(); + public abstract long getFullWifiLockTime(long batteryRealtime, int which); + public abstract long getScanWifiLockTime(long batteryRealtime, int which); public static abstract class Sensor { // Magic sensor number for the GPS. @@ -270,6 +294,22 @@ public abstract class BatteryStats implements Parcelable { public abstract long getPhoneOnTime(long batteryRealtime, int which); /** + * Returns the time in milliseconds that wifi has been on while the device was + * running on battery. + * + * {@hide} + */ + public abstract long getWifiOnTime(long batteryRealtime, int which); + + /** + * Returns the time in milliseconds that bluetooth has been on while the device was + * running on battery. + * + * {@hide} + */ + public abstract long getBluetoothOnTime(long batteryRealtime, int which); + + /** * Return whether we are currently running on battery. */ public abstract boolean getIsOnBattery(); @@ -292,6 +332,17 @@ public abstract class BatteryStats implements Parcelable { * @param curTime the amount of elapsed realtime in microseconds. */ public abstract long getBatteryRealtime(long curTime); + + /** + * Returns the battery percentage level at the last time the device was unplugged from power, + * or the last time it was booted while unplugged. + */ + public abstract int getUnpluggedStartLevel(); + + /** + * Returns the battery percentage level at the last time the device was plugged into power. + */ + public abstract int getPluggedStartLevel(); /** * Returns the total, last, or current battery uptime in microseconds. @@ -483,6 +534,8 @@ public abstract class BatteryStats implements Parcelable { final long totalUptime = computeUptime(rawUptime, which); final long screenOnTime = getScreenOnTime(batteryRealtime, which); final long phoneOnTime = getPhoneOnTime(batteryRealtime, which); + final long wifiOnTime = getWifiOnTime(batteryRealtime, which); + final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which); StringBuilder sb = new StringBuilder(128); @@ -496,7 +549,12 @@ public abstract class BatteryStats implements Parcelable { // Dump misc stats dumpLine(pw, 0 /* uid */, category, MISC_DATA, - screenOnTime / 1000, phoneOnTime / 1000); + screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000, bluetoothOnTime / 1000); + + if (which == STATS_UNPLUGGED) { + dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, getUnpluggedStartLevel(), + getPluggedStartLevel()); + } SparseArray<? extends Uid> uidStats = getUidStats(); final int NU = uidStats.size(); @@ -506,7 +564,15 @@ public abstract class BatteryStats implements Parcelable { // Dump Network stats per uid, if any long rx = u.getTcpBytesReceived(which); long tx = u.getTcpBytesSent(which); + long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which); + long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which); + if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx); + + if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0) { + dumpLine(pw, uid, category, WIFI_LOCK_DATA, + fullWifiLockOnTime, scanWifiLockOnTime); + } Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); if (wakelocks.size() > 0) { @@ -624,13 +690,35 @@ public abstract class BatteryStats implements Parcelable { + formatTimeMs(totalRealtime / 1000) + "realtime"); - long screenOnTime = getScreenOnTime(batteryRealtime, which); - long phoneOnTime = getPhoneOnTime(batteryRealtime, which); + final long screenOnTime = getScreenOnTime(batteryRealtime, which); + final long phoneOnTime = getPhoneOnTime(batteryRealtime, which); + final long wifiOnTime = getWifiOnTime(batteryRealtime, which); + final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which); pw.println(prefix + " Time with screen on: " + formatTimeMs(screenOnTime / 1000) + "(" + formatRatioLocked(screenOnTime, whichBatteryRealtime) + "), time with phone on: " + formatTimeMs(phoneOnTime / 1000) - + "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime) + ")"); + + "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime) + + "), time with wifi on: " + formatTimeMs(wifiOnTime / 1000) + + "(" + formatRatioLocked(wifiOnTime, whichBatteryRealtime) + + "), time with bluetooth on: " + formatTimeMs(bluetoothOnTime / 1000) + + "(" + formatRatioLocked(bluetoothOnTime, whichBatteryRealtime)+ ")"); + + pw.println(" "); + + if (which == STATS_UNPLUGGED) { + if (getIsOnBattery()) { + pw.println(prefix + " Device is currently unplugged"); + pw.println(prefix + " Discharge cycle start level: " + + getUnpluggedStartLevel()); + } else { + pw.println(prefix + " Device is currently plugged into power"); + pw.println(prefix + " Last discharge cycle start level: " + + getUnpluggedStartLevel()); + pw.println(prefix + " Last discharge cycle end level: " + + getPluggedStartLevel()); + } + } pw.println(" "); @@ -644,10 +732,23 @@ public abstract class BatteryStats implements Parcelable { long tcpReceived = u.getTcpBytesReceived(which); long tcpSent = u.getTcpBytesSent(which); + long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which); + long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which); + if (tcpReceived != 0 || tcpSent != 0) { pw.println(prefix + " Network: " + tcpReceived + " bytes received, " + tcpSent + " bytes sent"); } + if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0) { + pw.println(prefix + " Full Wifi Lock Time: " + + formatTime(fullWifiLockOnTime / 1000) + + "(" + formatRatioLocked(fullWifiLockOnTime, + whichBatteryRealtime)+ ")"); + pw.println(prefix + " Scan Wifi Lock Time: " + + formatTime(scanWifiLockOnTime / 1000) + + "(" + formatRatioLocked(scanWifiLockOnTime, + whichBatteryRealtime)+ ")"); + } Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats(); if (wakelocks.size() > 0) { diff --git a/core/java/android/os/Hardware.java b/core/java/android/os/Hardware.java index 3b6c9d7..efc5617 100644 --- a/core/java/android/os/Hardware.java +++ b/core/java/android/os/Hardware.java @@ -21,22 +21,29 @@ package android.os; */ public class Hardware { - /** - * Control the LED. - */ - public static native int setLedState(int colorARGB, int onMS, int offMS); - - /** - * Control the Flashlight - */ + + + /* ******************************************************************************** + * + * + * + * + * + * + * + * + * Don't add anything else to this class. Add it to HardwareService instead. + * + * + * + * + * + * + * + * ********************************************************************************/ + + public static native boolean getFlashlightEnabled(); public static native void setFlashlightEnabled(boolean on); public static native void enableCameraFlash(int milliseconds); - - /** - * Control the backlights - */ - public static native void setScreenBacklight(int brightness); - public static native void setKeyboardBacklight(boolean on); - public static native void setButtonBacklight(boolean on); } diff --git a/core/java/android/os/IHardwareService.aidl b/core/java/android/os/IHardwareService.aidl index 4f6029f..fb121bb 100755 --- a/core/java/android/os/IHardwareService.aidl +++ b/core/java/android/os/IHardwareService.aidl @@ -29,12 +29,10 @@ interface IHardwareService void setFlashlightEnabled(boolean on); void enableCameraFlash(int milliseconds); - // backlight support - void setScreenBacklight(int brightness); - void setKeyboardBacklight(boolean on); - void setButtonBacklight(boolean on); - - // LED support - void setLedState(int colorARGB, int onMS, int offMS); + // sets the brightness of the backlights (screen, keyboard, button) 0-255 + void setBacklights(int brightness); + + // for the phone + void setAttentionLight(boolean on); } diff --git a/core/java/android/os/Power.java b/core/java/android/os/Power.java index b53e227..47497e5 100644 --- a/core/java/android/os/Power.java +++ b/core/java/android/os/Power.java @@ -45,26 +45,6 @@ public class Power public static native void releaseWakeLock(String id); /** - * Flag to turn on and off the keyboard light. - */ - public static final int KEYBOARD_LIGHT = 0x00000001; - - /** - * Flag to turn on and off the screen backlight. - */ - public static final int SCREEN_LIGHT = 0x00000002; - - /** - * Flag to turn on and off the button backlight. - */ - public static final int BUTTON_LIGHT = 0x00000004; - - /** - * Flags to turn on and off all the backlights. - */ - public static final int ALL_LIGHTS = (KEYBOARD_LIGHT|SCREEN_LIGHT|BUTTON_LIGHT); - - /** * Brightness value for fully off */ public static final int BRIGHTNESS_OFF = 0; @@ -91,14 +71,6 @@ public class Power public static final int LOW_BATTERY_THRESHOLD = 10; /** - * Set the brightness for one or more lights - * - * @param mask flags indicating which lights to change brightness - * @param brightness new brightness value (0 = off, 255 = fully bright) - */ - public static native int setLightBrightness(int mask, int brightness); - - /** * Turn the screen on or off * * @param on Whether you want the screen on or off diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java index 04e7ef0..63f6dff 100644 --- a/core/java/android/os/RemoteCallbackList.java +++ b/core/java/android/os/RemoteCallbackList.java @@ -211,7 +211,7 @@ public class RemoteCallbackList<E extends IInterface> { for (Callback cb : mCallbacks.values()) { active[i++] = cb.mCallback; } - return N; + return i; } } diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java index d75a25f..4a709f6 100644 --- a/core/java/android/provider/Calendar.java +++ b/core/java/android/provider/Calendar.java @@ -1054,6 +1054,9 @@ public final class Calendar { if (cursor == null) { return; } + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "missed alarms found: " + cursor.getCount()); + } try { while (cursor.moveToNext()) { @@ -1068,6 +1071,8 @@ public final class Calendar { intent.putExtra(android.provider.Calendar.EVENT_END_TIME, end); PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); + Log.w(TAG, "rescheduling missed alarm, id: " + id + " begin: " + begin + + " end: " + end + " alarmTime: " + alarmTime); manager.set(AlarmManager.RTC_WAKEUP, alarmTime, sender); } } finally { diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index 10fe3f5..abd6934 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -22,6 +22,8 @@ import android.content.Context; import android.net.Uri; import android.provider.Contacts.People; import com.android.internal.telephony.CallerInfo; +import com.android.internal.telephony.Connection; + import android.text.TextUtils; import android.util.Log; @@ -137,7 +139,8 @@ public class CallLog { * if the contact is unknown. * @param context the context used to get the ContentResolver * @param number the phone number to be added to the calls db - * @param isPrivateNumber <code>true</code> if the call was marked as private by the network + * @param presentation the number presenting rules set by the network for + * "allowed", "payphone", "restricted" or "unknown" * @param callType enumerated values for "incoming", "outgoing", or "missed" * @param start time stamp for the call in milliseconds * @param duration call duration in seconds @@ -145,12 +148,14 @@ public class CallLog { * {@hide} */ public static Uri addCall(CallerInfo ci, Context context, String number, - boolean isPrivateNumber, int callType, long start, int duration) { + int presentation, int callType, long start, int duration) { final ContentResolver resolver = context.getContentResolver(); if (TextUtils.isEmpty(number)) { - if (isPrivateNumber) { + if (presentation == Connection.PRESENTATION_RESTRICTED) { number = CallerInfo.PRIVATE_NUMBER; + } else if (presentation == Connection.PRESENTATION_PAYPHONE) { + number = CallerInfo.PAYPHONE_NUMBER; } else { number = CallerInfo.UNKNOWN_NUMBER; } diff --git a/core/java/android/provider/Contacts.java b/core/java/android/provider/Contacts.java index 2aa77ea..be31c0a 100644 --- a/core/java/android/provider/Contacts.java +++ b/core/java/android/provider/Contacts.java @@ -1459,13 +1459,24 @@ public class Contacts { "com.android.contacts.action.SHOW_OR_CREATE_CONTACT"; /** - * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new contact if no matching - * contact found. Otherwise, default behavior is to prompt user with dialog before creating. - * - * <P>Type: BOOLEAN</P> + * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new + * contact if no matching contact found. Otherwise, default behavior is + * to prompt user with dialog before creating. + * <p> + * Type: BOOLEAN */ public static final String EXTRA_FORCE_CREATE = "com.android.contacts.action.FORCE_CREATE"; + + /** + * Used with {@link #SHOW_OR_CREATE_CONTACT} to specify an exact + * description to be shown when prompting user about creating a new + * contact. + * <p> + * Type: STRING + */ + public static final String EXTRA_CREATE_DESCRIPTION = + "com.android.contacts.action.CREATE_DESCRIPTION"; /** * Intents related to the Contacts app UI. diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java index 3aa4078..3c50707 100644 --- a/core/java/android/server/BluetoothA2dpService.java +++ b/core/java/android/server/BluetoothA2dpService.java @@ -63,6 +63,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { private final IntentFilter mIntentFilter; private HashMap<String, SinkState> mAudioDevices; private final AudioManager mAudioManager; + private final BluetoothDevice mBluetooth; private class SinkState { public String address; @@ -75,9 +76,8 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - BluetoothDevice device = - (BluetoothDevice)mContext.getSystemService(Context.BLUETOOTH_SERVICE); - if (device == null) { + mBluetooth = (BluetoothDevice) mContext.getSystemService(Context.BLUETOOTH_SERVICE); + if (mBluetooth == null) { throw new RuntimeException("Platform does not support Bluetooth"); } @@ -85,13 +85,12 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { throw new RuntimeException("Could not init BluetoothA2dpService"); } - mIntentFilter = new IntentFilter(BluetoothIntent.ENABLED_ACTION); - mIntentFilter.addAction(BluetoothIntent.DISABLED_ACTION); + mIntentFilter = new IntentFilter(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION); mIntentFilter.addAction(BluetoothIntent.BOND_STATE_CHANGED_ACTION); mIntentFilter.addAction(BluetoothIntent.REMOTE_DEVICE_CONNECTED_ACTION); mContext.registerReceiver(mReceiver, mIntentFilter); - if (device.isEnabled()) { + if (mBluetooth.isEnabled()) { onBluetoothEnable(); } } @@ -110,10 +109,17 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); String address = intent.getStringExtra(BluetoothIntent.ADDRESS); - if (action.equals(BluetoothIntent.ENABLED_ACTION)) { - onBluetoothEnable(); - } else if (action.equals(BluetoothIntent.DISABLED_ACTION)) { - onBluetoothDisable(); + if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION)) { + int state = intent.getIntExtra(BluetoothIntent.BLUETOOTH_STATE, + BluetoothError.ERROR); + switch (state) { + case BluetoothDevice.BLUETOOTH_STATE_ON: + onBluetoothEnable(); + break; + case BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF: + onBluetoothDisable(); + break; + } } else if (action.equals(BluetoothIntent.BOND_STATE_CHANGED_ACTION)) { int bondState = intent.getIntExtra(BluetoothIntent.BOND_STATE, BluetoothError.ERROR); @@ -145,9 +151,10 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { switch (msg.what) { case MESSAGE_CONNECT_TO: String address = (String)msg.obj; - // check device is still preferred, and nothing is currently - // connected - if (getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF && + // check bluetooth is still on, device is still preferred, and + // nothing is currently connected + if (mBluetooth.isEnabled() && + getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF && lookupSinksMatchingStates(new int[] { BluetoothA2dp.STATE_CONNECTING, BluetoothA2dp.STATE_CONNECTED, diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java index 9e9ba62..b7e3846 100644 --- a/core/java/android/server/BluetoothDeviceService.java +++ b/core/java/android/server/BluetoothDeviceService.java @@ -37,8 +37,10 @@ import android.content.Intent; import android.content.IntentFilter; import android.os.Binder; import android.os.Handler; +import android.os.IBinder; import android.os.Message; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemService; import android.provider.Settings; import android.util.Log; @@ -51,6 +53,8 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import com.android.internal.app.IBatteryStats; + public class BluetoothDeviceService extends IBluetoothDevice.Stub { private static final String TAG = "BluetoothDeviceService"; private static final boolean DBG = true; @@ -60,14 +64,18 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { private IntentFilter mIntentFilter; private boolean mIsAirplaneSensitive; private final BondState mBondState = new BondState(); // local cache of bondings - private volatile boolean mIsEnabled; // local cache of isEnabledNative() + private int mBluetoothState; private boolean mIsDiscovering; + private final IBatteryStats mBatteryStats; private final Context mContext; private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; + private static final int MESSAGE_REGISTER_SDP_RECORDS = 1; + private static final int MESSAGE_FINISH_DISABLE = 2; + static { classInitNative(); } @@ -75,6 +83,12 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { public BluetoothDeviceService(Context context) { mContext = context; + + // Need to do this in place of: + // mBatteryStats = BatteryStatsService.getService(); + // Since we can not import BatteryStatsService from here. This class really needs to be + // moved to java/services/com/android/server/ + mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo")); } /** Must be called after construction, and before any other method. @@ -87,7 +101,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { disableNative(); } - mIsEnabled = false; + setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_OFF); mIsDiscovering = false; mEventLoop = new BluetoothEventLoop(mContext, this); registerForAirplaneMode(); @@ -109,10 +123,16 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { public boolean isEnabled() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - return mIsEnabled; + return mBluetoothState == BluetoothDevice.BLUETOOTH_STATE_ON; } private native int isEnabledNative(); + public int getBluetoothState() { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + return mBluetoothState; + } + + /** * Bring down bluetooth and disable BT in settings. Returns true on success. */ @@ -124,17 +144,36 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { * Bring down bluetooth. Returns true on success. * * @param saveSetting If true, disable BT in settings - * */ public synchronized boolean disable(boolean saveSetting) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); + switch (mBluetoothState) { + case BluetoothDevice.BLUETOOTH_STATE_OFF: + return true; + case BluetoothDevice.BLUETOOTH_STATE_ON: + break; + default: + return false; + } if (mEnableThread != null && mEnableThread.isAlive()) { return false; } - if (!mIsEnabled) { - return true; + setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF); + + // Allow 3 seconds for profiles to gracefully disconnect + // TODO: Introduce a callback mechanism so that each profile can notify + // BluetoothDeviceService when it is done shutting down + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000); + return true; + } + + + private synchronized void finishDisable(boolean saveSetting) { + if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF) { + return; } mEventLoop.stop(); disableNative(); @@ -163,38 +202,37 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { intent.putExtra(BluetoothIntent.SCAN_MODE, BluetoothDevice.SCAN_MODE_NONE); mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mIsEnabled = false; + mIsDiscovering = false; + if (saveSetting) { persistBluetoothOnSetting(false); } - mIsDiscovering = false; - intent = new Intent(BluetoothIntent.DISABLED_ACTION); - mContext.sendBroadcast(intent, BLUETOOTH_PERM); - return true; + + setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_OFF); + + // Log bluetooth off to battery stats. + long ident = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteBluetoothOff(); + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } } - /** - * Bring up bluetooth, asynchronously, and enable BT in settings. - * This turns on/off the underlying hardware. - * - * @return True on success (so far), guaranteeing the callback with be - * notified when complete. - */ - public boolean enable(IBluetoothDeviceCallback callback) { - return enable(callback, true); + /** Bring up BT and persist BT on in settings */ + public boolean enable() { + return enable(true); } /** * Enable this Bluetooth device, asynchronously. * This turns on/off the underlying hardware. * - * @param saveSetting If true, enable BT in settings - * - * @return True on success (so far), guaranteeing the callback with be - * notified when complete. + * @param saveSetting If true, persist the new state of BT in settings + * @return True on success (so far) */ - public synchronized boolean enable(IBluetoothDeviceCallback callback, - boolean saveSetting) { + public synchronized boolean enable(boolean saveSetting) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); @@ -202,28 +240,49 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { if (mIsAirplaneSensitive && isAirplaneModeOn()) { return false; } - if (mIsEnabled) { + if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_OFF) { return false; } if (mEnableThread != null && mEnableThread.isAlive()) { return false; } - mEnableThread = new EnableThread(callback, saveSetting); + setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_ON); + mEnableThread = new EnableThread(saveSetting); mEnableThread.start(); return true; } - private static final int REGISTER_SDP_RECORDS = 1; + private synchronized void setBluetoothState(int state) { + if (state == mBluetoothState) { + return; + } + + if (DBG) log("Bluetooth state " + mBluetoothState + " -> " + state); + + Intent intent = new Intent(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION); + intent.putExtra(BluetoothIntent.BLUETOOTH_PREVIOUS_STATE, mBluetoothState); + intent.putExtra(BluetoothIntent.BLUETOOTH_STATE, state); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + + mBluetoothState = state; + + mContext.sendBroadcast(intent, BLUETOOTH_PERM); + } + private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { - case REGISTER_SDP_RECORDS: + case MESSAGE_REGISTER_SDP_RECORDS: //TODO: Don't assume HSP/HFP is running, don't use sdptool, if (isEnabled()) { SystemService.start("hsag"); SystemService.start("hfag"); } + break; + case MESSAGE_FINISH_DISABLE: + finishDisable(msg.arg1 != 0); + break; } } }; @@ -231,10 +290,8 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { private EnableThread mEnableThread; private class EnableThread extends Thread { - private final IBluetoothDeviceCallback mEnableCallback; private final boolean mSaveSetting; - public EnableThread(IBluetoothDeviceCallback callback, boolean saveSetting) { - mEnableCallback = callback; + public EnableThread(boolean saveSetting) { mSaveSetting = saveSetting; } public void run() { @@ -244,7 +301,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { boolean running = false; while ((retryCount-- > 0) && !running) { mEventLoop.start(); - // it may take a momement for the other thread to do its + // it may take a momement for the other thread to do its // thing. Check periodically for a while. int pollCount = 5; while ((pollCount-- > 0) && !running) { @@ -264,36 +321,37 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { } } - if (mEnableCallback != null) { - try { - mEnableCallback.onEnableResult(res ? - BluetoothDevice.RESULT_SUCCESS : - BluetoothDevice.RESULT_FAILURE); - } catch (RemoteException e) {} - } if (res) { - mIsEnabled = true; if (mSaveSetting) { persistBluetoothOnSetting(true); } mIsDiscovering = false; mBondState.loadBondState(); - mHandler.sendMessageDelayed(mHandler.obtainMessage(REGISTER_SDP_RECORDS), 3000); + mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS), + 3000); - // Update mode - mEventLoop.onModeChanged(getModeNative()); + // Log bluetooth on to battery stats. + long ident = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteBluetoothOn(); + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } } - Intent intent = null; + + mEnableThread = null; + + setBluetoothState(res ? + BluetoothDevice.BLUETOOTH_STATE_ON : + BluetoothDevice.BLUETOOTH_STATE_OFF); + if (res) { - intent = new Intent(BluetoothIntent.ENABLED_ACTION); - } else { - intent = new Intent(BluetoothIntent.DISABLED_ACTION); + // Update mode + mEventLoop.onModeChanged(getModeNative()); } - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mEnableThread = null; } } @@ -320,18 +378,24 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { private final HashMap<String, Integer> mState = new HashMap<String, Integer>(); private final HashMap<String, Integer> mPinAttempt = new HashMap<String, Integer>(); private final ArrayList<String> mAutoPairingFailures = new ArrayList<String>(); - // List of all the vendor_id prefix of Bluetooth addresses for which - // auto pairing is not attempted + // List of all the vendor_id prefix of Bluetooth addresses for + // which auto pairing is not attempted. + // The following companies are included in the list below: + // ALPS (lexus), Murata (Prius 2007, Nokia 616), TEMIC SDS (Porsche, Audi), + // Parrot, Zhongshan General K-mate Electronics, Great Well + // Electronics, Flaircomm Electronics, Jatty Electronics, Delphi, + // Clarion, Novero, Denso (Lexus, Toyota), Johnson Controls (Acura), private final ArrayList<String> mAutoPairingBlacklisted = new ArrayList<String>(Arrays.asList( - "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", //ALPS - "00:21:4F", "00:23:06", "00:24:33", "00:A0:79", // ALPS - "00:0E:6D", "00:13:E0", "00:21:E8", "00:60:57",// Murata for Prius 2007 - "00:0E:9F" // TEMIC SDS for Porsche + "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", "00:21:4F", + "00:23:06", "00:24:33", "00:A0:79", "00:0E:6D", "00:13:E0", "00:21:E8", + "00:60:57", "00:0E:9F", "00:12:1C", "00:18:91", "00:18:96", "00:13:04", + "00:16:FD", "00:22:A0", "00:0B:4C", "00:60:6F", "00:23:3D", "00:C0:59", + "00:0A:30" )); public synchronized void loadBondState() { - if (!mIsEnabled) { + if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_TURNING_ON) { return; } String[] bonds = listBondingsNative(); @@ -1051,7 +1115,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { // If bluetooth is currently expected to be on, then enable or disable bluetooth if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) { if (enabled) { - enable(null, false); + enable(false); } else { disable(false); } @@ -1079,52 +1143,63 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mIsEnabled) { - pw.println("\nBluetooth ENABLED: " + getAddress() + " (" + getName() + ")"); - pw.println("\nisDiscovering() = " + isDiscovering()); - - BluetoothHeadset headset = new BluetoothHeadset(mContext, null); - - String[] addresses = listRemoteDevices(); - - pw.println("\n--Known devices--"); - for (String address : addresses) { - pw.printf("%s %10s (%d) %s\n", address, - toBondStateString(mBondState.getBondState(address)), - mBondState.getAttempt(address), - getRemoteName(address)); - } - - addresses = listAclConnections(); - pw.println("\n--ACL connected devices--"); - for (String address : addresses) { - pw.println(address); - } - - // Rather not do this from here, but no-where else and I need this - // dump - pw.println("\n--Headset Service--"); - switch (headset.getState()) { - case BluetoothHeadset.STATE_DISCONNECTED: - pw.println("getState() = STATE_DISCONNECTED"); - break; - case BluetoothHeadset.STATE_CONNECTING: - pw.println("getState() = STATE_CONNECTING"); - break; - case BluetoothHeadset.STATE_CONNECTED: - pw.println("getState() = STATE_CONNECTED"); - break; - case BluetoothHeadset.STATE_ERROR: - pw.println("getState() = STATE_ERROR"); - break; - } - pw.println("getHeadsetAddress() = " + headset.getHeadsetAddress()); - headset.close(); - - } else { - pw.println("\nBluetooth DISABLED"); - } - pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive); + pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive + "\n"); + + switch(mBluetoothState) { + case BluetoothDevice.BLUETOOTH_STATE_OFF: + pw.println("\nBluetooth OFF\n"); + return; + case BluetoothDevice.BLUETOOTH_STATE_TURNING_ON: + pw.println("\nBluetooth TURNING ON\n"); + return; + case BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF: + pw.println("\nBluetooth TURNING OFF\n"); + return; + case BluetoothDevice.BLUETOOTH_STATE_ON: + pw.println("\nBluetooth ON\n"); + } + + pw.println("\nLocal address = " + getAddress()); + pw.println("\nLocal name = " + getName()); + pw.println("\nisDiscovering() = " + isDiscovering()); + + BluetoothHeadset headset = new BluetoothHeadset(mContext, null); + + String[] addresses = listRemoteDevices(); + + pw.println("\n--Known devices--"); + for (String address : addresses) { + pw.printf("%s %10s (%d) %s\n", address, + toBondStateString(mBondState.getBondState(address)), + mBondState.getAttempt(address), + getRemoteName(address)); + } + + addresses = listAclConnections(); + pw.println("\n--ACL connected devices--"); + for (String address : addresses) { + pw.println(address); + } + + // Rather not do this from here, but no-where else and I need this + // dump + pw.println("\n--Headset Service--"); + switch (headset.getState()) { + case BluetoothHeadset.STATE_DISCONNECTED: + pw.println("getState() = STATE_DISCONNECTED"); + break; + case BluetoothHeadset.STATE_CONNECTING: + pw.println("getState() = STATE_CONNECTING"); + break; + case BluetoothHeadset.STATE_CONNECTED: + pw.println("getState() = STATE_CONNECTED"); + break; + case BluetoothHeadset.STATE_ERROR: + pw.println("getState() = STATE_ERROR"); + break; + } + pw.println("getHeadsetAddress() = " + headset.getHeadsetAddress()); + headset.close(); } /* package */ static int bluezStringToScanMode(String mode) { @@ -1159,3 +1234,4 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { Log.d(TAG, msg); } } + diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index 8e77eed..6be8eb9 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -46,10 +46,10 @@ class BluetoothEventLoop { private Thread mThread; private boolean mStarted; private boolean mInterrupted; - private HashMap<String, Integer> mPasskeyAgentRequestData; - private HashMap<String, IBluetoothDeviceCallback> mGetRemoteServiceChannelCallbacks; - private BluetoothDeviceService mBluetoothService; - private Context mContext; + private final HashMap<String, Integer> mPasskeyAgentRequestData; + private final HashMap<String, IBluetoothDeviceCallback> mGetRemoteServiceChannelCallbacks; + private final BluetoothDeviceService mBluetoothService; + private final Context mContext; private static final int EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 1; private static final int EVENT_RESTART_BLUETOOTH = 2; @@ -77,7 +77,7 @@ class BluetoothEventLoop { break; case EVENT_RESTART_BLUETOOTH: mBluetoothService.disable(); - mBluetoothService.enable(null); + mBluetoothService.enable(); break; } } @@ -309,6 +309,12 @@ class BluetoothEventLoop { address = address.toUpperCase(); mPasskeyAgentRequestData.put(address, new Integer(nativeData)); + if (mBluetoothService.getBluetoothState() == BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF) { + // shutdown path + mBluetoothService.cancelPin(address); + return; + } + if (mBluetoothService.getBondState().getBondState(address) == BluetoothDevice.BOND_BONDING) { // we initiated the bonding @@ -347,7 +353,7 @@ class BluetoothEventLoop { private boolean onAuthAgentAuthorize(String address, String service, String uuid) { boolean authorized = false; - if (service.endsWith("service_audio")) { + if (mBluetoothService.isEnabled() && service.endsWith("service_audio")) { BluetoothA2dp a2dp = new BluetoothA2dp(mContext); authorized = a2dp.getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF; if (authorized) { diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java index 8495714..6f0be3a 100644 --- a/core/java/android/text/Html.java +++ b/core/java/android/text/Html.java @@ -28,6 +28,8 @@ import org.xml.sax.XMLReader; import android.content.res.Resources; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.text.style.AbsoluteSizeSpan; +import android.text.style.AlignmentSpan; import android.text.style.CharacterStyle; import android.text.style.ForegroundColorSpan; import android.text.style.ImageSpan; @@ -41,6 +43,7 @@ import android.text.style.SuperscriptSpan; import android.text.style.TypefaceSpan; import android.text.style.URLSpan; import android.text.style.UnderlineSpan; +import android.util.Log; import com.android.internal.util.XmlUtils; import java.io.IOException; @@ -137,11 +140,52 @@ public class Html { */ public static String toHtml(Spanned text) { StringBuilder out = new StringBuilder(); + withinHtml(out, text); + return out.toString(); + } + + private static void withinHtml(StringBuilder out, Spanned text) { int len = text.length(); int next; for (int i = 0; i < text.length(); i = next) { - next = text.nextSpanTransition(i, len, QuoteSpan.class); + next = text.nextSpanTransition(i, len, ParagraphStyle.class); + ParagraphStyle[] style = text.getSpans(i, next, ParagraphStyle.class); + if (style.length > 0) { + out.append("<div "); + } + for(int j = 0; j < style.length; j++) { + if (style[j] instanceof AlignmentSpan) { + out.append("align=\""); + Layout.Alignment align = + ((AlignmentSpan) style[j]).getAlignment(); + if (align == Layout.Alignment.ALIGN_CENTER) { + out.append("center"); + } else if (align == Layout.Alignment.ALIGN_OPPOSITE) { + out.append("right"); + } else { + out.append("left"); + } + out.append("\" "); + } + } + if (style.length > 0) { + out.append(">"); + } + + withinDiv(out, text, i, next); + + if (style.length > 0) { + out.append("</div>"); + } + } + } + + private static void withinDiv(StringBuilder out, Spanned text, + int start, int end) { + int next; + for (int i = start; i < end; i = next) { + next = text.nextSpanTransition(i, end, QuoteSpan.class); QuoteSpan[] quotes = text.getSpans(i, next, QuoteSpan.class); for (QuoteSpan quote: quotes) { @@ -154,8 +198,6 @@ public class Html { out.append("</blockquote>\n"); } } - - return out.toString(); } private static void withinBlockquote(StringBuilder out, Spanned text, @@ -234,11 +276,32 @@ public class Html { // Don't output the dummy character underlying the image. i = next; } + if (style[j] instanceof AbsoluteSizeSpan) { + out.append("<font size =\""); + out.append(((AbsoluteSizeSpan) style[j]).getSize() / 6); + out.append("\">"); + } + if (style[j] instanceof ForegroundColorSpan) { + out.append("<font color =\"#"); + String color = Integer.toHexString(((ForegroundColorSpan) + style[j]).getForegroundColor() + 0x01000000); + while (color.length() < 6) { + color = "0" + color; + } + out.append(color); + out.append("\">"); + } } withinStyle(out, text, i, next); for (int j = style.length - 1; j >= 0; j--) { + if (style[j] instanceof ForegroundColorSpan) { + out.append("</font>"); + } + if (style[j] instanceof AbsoluteSizeSpan) { + out.append("</font>"); + } if (style[j] instanceof URLSpan) { out.append("</a>"); } diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index 95acf9d..23e740d 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -16,6 +16,8 @@ package android.text; +import android.emoji.EmojiFactory; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; @@ -36,6 +38,20 @@ import android.view.KeyEvent; * For text that will not change, use a {@link StaticLayout}. */ public abstract class Layout { + /* package */ static final EmojiFactory EMOJI_FACTORY = + EmojiFactory.newAvailableInstance(); + /* package */ static final int MIN_EMOJI, MAX_EMOJI; + + static { + if (EMOJI_FACTORY != null) { + MIN_EMOJI = EMOJI_FACTORY.getMinimumAndroidPua(); + MAX_EMOJI = EMOJI_FACTORY.getMaximumAndroidPua(); + } else { + MIN_EMOJI = -1; + MAX_EMOJI = -1; + } + }; + /** * Return how wide a layout would be necessary to display the * specified text with one line per paragraph. @@ -445,7 +461,9 @@ public abstract class Layout { public abstract int getParagraphDirection(int line); /** - * Returns whether the specified line contains one or more tabs. + * Returns whether the specified line contains one or more + * characters that need to be handled specially, like tabs + * or emoji. */ public abstract boolean getLineContainsTab(int line); @@ -1352,6 +1370,26 @@ public abstract class Layout { h = dir * nextTab(text, start, end, h * dir, parspans); segstart = j + 1; + } else if (hasTabs && buf[j] >= 0xD800 && buf[j] <= 0xDFFF && j + 1 < there) { + int emoji = Character.codePointAt(buf, j); + + if (emoji >= MIN_EMOJI && emoji <= MAX_EMOJI) { + Bitmap bm = EMOJI_FACTORY. + getBitmapFromAndroidPua(emoji); + + if (bm != null) { + h += Styled.drawText(canvas, text, + start + segstart, start + j, + dir, (i & 1) != 0, x + h, + top, y, bottom, paint, workPaint, + start + j != end); + + canvas.drawBitmap(bm, x + h, y - bm.getHeight(), paint); + h += bm.getWidth(); + j++; + segstart = j + 1; + } + } } } @@ -1394,7 +1432,22 @@ public abstract class Layout { int segstart = here; for (int j = hasTabs ? here : there; j <= there; j++) { - if (j == there || buf[j] == '\t') { + int codept = 0; + Bitmap bm = null; + + if (hasTabs && j < there) { + codept = buf[j]; + } + + if (codept >= 0xD800 && codept <= 0xDFFF && j + 1 < there) { + codept = Character.codePointAt(buf, j); + + if (codept >= MIN_EMOJI && codept <= MAX_EMOJI) { + bm = EMOJI_FACTORY.getBitmapFromAndroidPua(codept); + } + } + + if (j == there || codept == '\t' || bm != null) { float segw; if (offset < start + j || @@ -1449,6 +1502,16 @@ public abstract class Layout { h = dir * nextTab(text, start, end, h * dir, tabs); } + if (bm != null) { + if (dir == DIR_RIGHT_TO_LEFT) { + h -= bm.getWidth(); + } else { + h += bm.getWidth(); + } + + j++; + } + segstart = j + 1; } } @@ -1488,7 +1551,22 @@ public abstract class Layout { } for (int i = hasTabs ? 0 : len; i <= len; i++) { - if (i == len || buf[i] == '\t') { + int codept = 0; + Bitmap bm = null; + + if (hasTabs && i < len) { + codept = buf[i]; + } + + if (codept >= 0xD800 && codept <= 0xDFFF && i < len) { + codept = Character.codePointAt(buf, i); + + if (codept >= MIN_EMOJI && codept <= MAX_EMOJI) { + bm = EMOJI_FACTORY.getBitmapFromAndroidPua(codept); + } + } + + if (i == len || codept == '\t' || bm != null) { workPaint.baselineShift = 0; h += Styled.measureText(paint, workPaint, text, @@ -1505,8 +1583,14 @@ public abstract class Layout { } } - if (i != len) - h = nextTab(text, start, end, h, tabs); + if (i != len) { + if (bm == null) { + h = nextTab(text, start, end, h, tabs); + } else { + h += bm.getWidth(); + i++; + } + } if (fm != null) { if (fm.ascent < ab) { @@ -1522,6 +1606,17 @@ public abstract class Layout { if (fm.bottom > bot) { bot = fm.bottom; } + + if (bm != null) { + int ht = -bm.getHeight(); + + if (ht < ab) { + ab = ht; + } + if (ht < top) { + top = ht; + } + } } here = i + 1; diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 0fef40b..720d15a 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -16,6 +16,7 @@ package android.text; +import android.graphics.Bitmap; import android.graphics.Paint; import com.android.internal.util.ArrayUtils; import android.util.Log; @@ -421,11 +422,16 @@ extends Layout // dump(chdirs, n, "final"); - // extra: enforce that all tabs go the primary direction + // extra: enforce that all tabs and surrogate characters go the + // primary direction + // TODO: actually do directions right for surrogates for (int j = 0; j < n; j++) { - if (chs[j] == '\t') + char c = chs[j]; + + if (c == '\t' || (c >= 0xD800 && c <= 0xDFFF)) { chdirs[j] = SOR; + } } // extra: enforce that object replacements go to the @@ -548,16 +554,29 @@ extends Layout char c = chs[j - start]; float before = w; - switch (c) { - case '\n': - break; - - case '\t': + if (c == '\n') { + ; + } else if (c == '\t') { w = Layout.nextTab(sub, start, end, w, null); tab = true; - break; - - default: + } else if (c >= 0xD800 && c <= 0xDFFF && j + 1 < next) { + int emoji = Character.codePointAt(chs, j - start); + + if (emoji >= MIN_EMOJI && emoji <= MAX_EMOJI) { + Bitmap bm = EMOJI_FACTORY. + getBitmapFromAndroidPua(emoji); + + if (bm != null) { + w += bm.getWidth(); + tab = true; + j++; + } else { + w += widths[j - start + (end - start)]; + } + } else { + w += widths[j - start + (end - start)]; + } + } else { w += widths[j - start + (end - start)]; } diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java index f7ac522..23f3e3c 100644 --- a/core/java/android/view/GestureDetector.java +++ b/core/java/android/view/GestureDetector.java @@ -201,8 +201,6 @@ public class GestureDetector { private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout(); private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout(); - // TODO make new double-tap timeout, and define its events (i.e. either time - // between down-down or time between up-down) private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout(); // constants for Message.what used by GestureHandler below diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index a856b24..15e7eb2 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -62,7 +62,8 @@ interface IWindowManager void addAppToken(int addPos, IApplicationToken token, int groupId, int requestedOrientation, boolean fullscreen); void setAppGroupId(IBinder token, int groupId); - Configuration updateOrientationFromAppTokens(IBinder freezeThisOneIfNeeded); + Configuration updateOrientationFromAppTokens(in Configuration currentConfig, + IBinder freezeThisOneIfNeeded); void setAppOrientation(IApplicationToken token, int requestedOrientation); int getAppOrientation(IApplicationToken token); void setFocusedApp(IBinder token, boolean moveFocusNow); diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 430cc71..41779ba 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -235,6 +235,22 @@ public class KeyEvent implements Parcelable { public static final int FLAG_KEEP_TOUCH_MODE = 0x4; /** + * This mask is set if an event was known to come from a trusted part + * of the system. That is, the event is known to come from the user, + * and could not have been spoofed by a third party component. + */ + public static final int FLAG_FROM_SYSTEM = 0x8; + + /** + * This mask is used for compatibility, to identify enter keys that are + * coming from an IME whose enter key has been auto-labelled "next" or + * "done". This allows TextView to dispatch these as normal enter keys + * for old applications, but still do the appropriate action when + * receiving them. + */ + public static final int FLAG_EDITOR_ACTION = 0x10; + + /** * Returns the maximum keycode. */ public static int getMaxKeyCode() { @@ -440,6 +456,22 @@ public class KeyEvent implements Parcelable { } /** + * Make an exact copy of an existing key event. + */ + public KeyEvent(KeyEvent origEvent) { + mDownTime = origEvent.mDownTime; + mEventTime = origEvent.mEventTime; + mAction = origEvent.mAction; + mKeyCode = origEvent.mKeyCode; + mRepeatCount = origEvent.mRepeatCount; + mMetaState = origEvent.mMetaState; + mDeviceId = origEvent.mDeviceId; + mScancode = origEvent.mScancode; + mFlags = origEvent.mFlags; + mCharacters = origEvent.mCharacters; + } + + /** * Copy an existing key event, modifying its time and repeat count. * * @param origEvent The existing event to be copied. @@ -461,12 +493,26 @@ public class KeyEvent implements Parcelable { } /** + * Create a new key event that is the same as the given one, but whose + * event time and repeat count are replaced with the given value. + * + * @param event The existing event to be copied. This is not modified. + * @param eventTime The new event time + * (in {@link android.os.SystemClock#uptimeMillis}) of the event. + * @param newRepeat The new repeat count of the event. + */ + public static KeyEvent changeTimeRepeat(KeyEvent event, long eventTime, + int newRepeat) { + return new KeyEvent(event, eventTime, newRepeat); + } + + /** * Copy an existing key event, modifying its action. * * @param origEvent The existing event to be copied. * @param action The new action code of the event. */ - public KeyEvent(KeyEvent origEvent, int action) { + private KeyEvent(KeyEvent origEvent, int action) { mDownTime = origEvent.mDownTime; mEventTime = origEvent.mEventTime; mAction = action; @@ -481,6 +527,30 @@ public class KeyEvent implements Parcelable { } /** + * Create a new key event that is the same as the given one, but whose + * action is replaced with the given value. + * + * @param event The existing event to be copied. This is not modified. + * @param action The new action code of the event. + */ + public static KeyEvent changeAction(KeyEvent event, int action) { + return new KeyEvent(event, action); + } + + /** + * Create a new key event that is the same as the given one, but whose + * flags are replaced with the given value. + * + * @param event The existing event to be copied. This is not modified. + * @param flags The new flags constant. + */ + public static KeyEvent changeFlags(KeyEvent event, int flags) { + event = new KeyEvent(event); + event.mFlags = flags; + return event; + } + + /** * Don't use in new code, instead explicitly check * {@link #getAction()}. * diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index c3e00c4..04447ca 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3409,6 +3409,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback { if (imm != null && (mPrivateFlags & FOCUSED) != 0) { imm.focusOut(this); } + if (mPendingCheckForLongPress != null) { + removeCallbacks(mPendingCheckForLongPress); + } } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) { imm.focusIn(this); } @@ -7656,7 +7659,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { private int mOriginalWindowAttachCount; public void run() { - if (isPressed() && (mParent != null) && hasWindowFocus() + if (isPressed() && (mParent != null) && mOriginalWindowAttachCount == mWindowAttachCount) { if (performLongClick()) { mHasPerformedLongPress = true; diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 6ea7a82..f604bc5 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -19,6 +19,7 @@ package android.view; import android.util.Log; import android.util.DisplayMetrics; import android.content.res.Resources; +import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.os.Environment; @@ -800,7 +801,7 @@ public class ViewDebug { View view = root.getRootView(); if (view instanceof ViewGroup) { ViewGroup group = (ViewGroup) view; - dumpViewHierarchyWithProperties(group, out, 0); + dumpViewHierarchyWithProperties(group.getContext(), group, out, 0); } out.write("DONE."); out.newLine(); @@ -838,9 +839,9 @@ public class ViewDebug { return view.getClass().getName().equals(className) && view.hashCode() == hashCode; } - private static void dumpViewHierarchyWithProperties(ViewGroup group, + private static void dumpViewHierarchyWithProperties(Context context, ViewGroup group, BufferedWriter out, int level) { - if (!dumpViewWithProperties(group, out, level)) { + if (!dumpViewWithProperties(context, group, out, level)) { return; } @@ -848,14 +849,16 @@ public class ViewDebug { for (int i = 0; i < count; i++) { final View view = group.getChildAt(i); if (view instanceof ViewGroup) { - dumpViewHierarchyWithProperties((ViewGroup) view, out, level + 1); + dumpViewHierarchyWithProperties(context, (ViewGroup) view, out, level + 1); } else { - dumpViewWithProperties(view, out, level + 1); + dumpViewWithProperties(context, view, out, level + 1); } } } - private static boolean dumpViewWithProperties(View view, BufferedWriter out, int level) { + private static boolean dumpViewWithProperties(Context context, View view, + BufferedWriter out, int level) { + try { for (int i = 0; i < level; i++) { out.write(' '); @@ -864,7 +867,7 @@ public class ViewDebug { out.write('@'); out.write(Integer.toHexString(view.hashCode())); out.write(' '); - dumpViewProperties(view, out); + dumpViewProperties(context, view, out); out.newLine(); } catch (IOException e) { Log.w("View", "Error while dumping hierarchy tree"); @@ -945,23 +948,26 @@ public class ViewDebug { return methods; } - private static void dumpViewProperties(Object view, BufferedWriter out) throws IOException { - dumpViewProperties(view, out, ""); + private static void dumpViewProperties(Context context, Object view, + BufferedWriter out) throws IOException { + + dumpViewProperties(context, view, out, ""); } - private static void dumpViewProperties(Object view, BufferedWriter out, String prefix) - throws IOException { + private static void dumpViewProperties(Context context, Object view, + BufferedWriter out, String prefix) throws IOException { + Class<?> klass = view.getClass(); do { - exportFields(view, out, klass, prefix); - exportMethods(view, out, klass, prefix); + exportFields(context, view, out, klass, prefix); + exportMethods(context, view, out, klass, prefix); klass = klass.getSuperclass(); } while (klass != Object.class); } - private static void exportMethods(Object view, BufferedWriter out, Class<?> klass, - String prefix) throws IOException { + private static void exportMethods(Context context, Object view, BufferedWriter out, + Class<?> klass, String prefix) throws IOException { final Method[] methods = getExportedPropertyMethods(klass); @@ -976,9 +982,9 @@ public class ViewDebug { if (returnType == int.class) { final ExportedProperty property = sAnnotations.get(method); - if (property.resolveId() && view instanceof View) { + if (property.resolveId() && context != null) { final int id = (Integer) methodValue; - methodValue = resolveId(view, id); + methodValue = resolveId(context, id); } else { final IntToString[] mapping = property.mapping(); if (mapping.length > 0) { @@ -1005,11 +1011,11 @@ public class ViewDebug { final String valuePrefix = prefix + method.getName() + '_'; final String suffix = "()"; - exportUnrolledArray(view, out, property, array, valuePrefix, suffix); + exportUnrolledArray(context, out, property, array, valuePrefix, suffix); } else if (!returnType.isPrimitive()) { final ExportedProperty property = sAnnotations.get(method); if (property.deepExport()) { - dumpViewProperties(methodValue, out, prefix + property.prefix()); + dumpViewProperties(context, methodValue, out, prefix + property.prefix()); continue; } } @@ -1021,8 +1027,9 @@ public class ViewDebug { } } - private static void exportFields(Object view, BufferedWriter out, Class<?> klass, String prefix) - throws IOException { + private static void exportFields(Context context, Object view, BufferedWriter out, + Class<?> klass, String prefix) throws IOException { + final Field[] fields = getExportedPropertyFields(klass); int count = fields.length; @@ -1036,9 +1043,9 @@ public class ViewDebug { if (type == int.class) { final ExportedProperty property = sAnnotations.get(field); - if (property.resolveId() && view instanceof View) { + if (property.resolveId() && context != null) { final int id = field.getInt(view); - fieldValue = resolveId(view, id); + fieldValue = resolveId(context, id); } else { final IntToString[] mapping = property.mapping(); if (mapping.length > 0) { @@ -1063,14 +1070,15 @@ public class ViewDebug { final String valuePrefix = prefix + field.getName() + '_'; final String suffix = ""; - exportUnrolledArray(view, out, property, array, valuePrefix, suffix); + exportUnrolledArray(context, out, property, array, valuePrefix, suffix); // We exit here! return; } else if (!type.isPrimitive()) { final ExportedProperty property = sAnnotations.get(field); if (property.deepExport()) { - dumpViewProperties(field.get(view), out, prefix + property.prefix()); + dumpViewProperties(context, field.get(view), out, + prefix + property.prefix()); continue; } } @@ -1096,7 +1104,7 @@ public class ViewDebug { out.write(' '); } - private static void exportUnrolledArray(Object view, BufferedWriter out, + private static void exportUnrolledArray(Context context, BufferedWriter out, ExportedProperty property, int[] array, String prefix, String suffix) throws IOException { @@ -1106,7 +1114,7 @@ public class ViewDebug { final IntToString[] mapping = property.mapping(); final boolean hasMapping = mapping.length > 0; - final boolean resolveId = property.resolveId() && view instanceof View; + final boolean resolveId = property.resolveId() && context != null; final int valuesCount = array.length; for (int j = 0; j < valuesCount; j++) { @@ -1140,16 +1148,16 @@ public class ViewDebug { } if (resolveId) { - value = (String) resolveId(view, intValue); + value = (String) resolveId(context, intValue); } writeEntry(out, prefix, name, suffix, value); } } - private static Object resolveId(Object view, int id) { + private static Object resolveId(Context context, int id) { Object fieldValue; - final Resources resources = ((View) view).getContext().getResources(); + final Resources resources = context.getResources(); if (id >= 0) { try { fieldValue = resources.getResourceTypeName(id) + '/' + diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index dd2b154..fbb4d42 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -470,11 +470,20 @@ public final class ViewRoot extends Handler implements ViewParent, void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) { synchronized (this) { + int oldSoftInputMode = mWindowAttributes.softInputMode; mWindowAttributes.copyFrom(attrs); if (newView) { mSoftInputMode = attrs.softInputMode; requestLayout(); } + // Don't lose the mode we last auto-computed. + if ((attrs.softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) + == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) { + mWindowAttributes.softInputMode = (mWindowAttributes.softInputMode + & ~WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) + | (oldSoftInputMode + & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST); + } mWindowAttributesChanged = true; scheduleTraversals(); } @@ -1485,7 +1494,7 @@ public final class ViewRoot extends Handler implements ViewParent, + msg.obj + " to " + mView); deliverKeyEvent((KeyEvent)msg.obj, true); break; - case DISPATCH_POINTER: + case DISPATCH_POINTER: { MotionEvent event = (MotionEvent)msg.obj; boolean didFinish; @@ -1571,7 +1580,7 @@ public final class ViewRoot extends Handler implements ViewParent, // Let the exception fall through -- the looper will catch // it and take care of the bad app for us. } - break; + } break; case DISPATCH_TRACKBALL: deliverTrackballEvent((MotionEvent)msg.obj); break; @@ -1657,12 +1666,19 @@ public final class ViewRoot extends Handler implements ViewParent, case DIE: dispatchDetachedFromWindow(); break; - case DISPATCH_KEY_FROM_IME: + case DISPATCH_KEY_FROM_IME: { if (LOCAL_LOGV) Log.v( "ViewRoot", "Dispatching key " + msg.obj + " from IME to " + mView); + KeyEvent event = (KeyEvent)msg.obj; + if ((event.getFlags()&KeyEvent.FLAG_FROM_SYSTEM) != 0) { + // The IME is trying to say this event is from the + // system! Bad bad bad! + event = KeyEvent.changeFlags(event, + event.getFlags()&~KeyEvent.FLAG_FROM_SYSTEM); + } deliverKeyEventToViewHierarchy((KeyEvent)msg.obj, false); - break; + } break; case FINISH_INPUT_CONNECTION: { InputMethodManager imm = InputMethodManager.peekInstance(); if (imm != null) { diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java index 47b52e4..4230afa 100644 --- a/core/java/android/view/ViewTreeObserver.java +++ b/core/java/android/view/ViewTreeObserver.java @@ -18,7 +18,7 @@ package android.view; import android.graphics.Rect; -import java.util.ArrayList; +import java.util.concurrent.CopyOnWriteArrayList; /** * A view tree observer is used to register listeners that can be notified of global @@ -30,12 +30,12 @@ import java.util.ArrayList; * for more information. */ public final class ViewTreeObserver { - private ArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners; - private ArrayList<OnGlobalLayoutListener> mOnGlobalLayoutListeners; - private ArrayList<OnPreDrawListener> mOnPreDrawListeners; - private ArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners; - private ArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners; - private ArrayList<OnScrollChangedListener> mOnScrollChangedListeners; + private CopyOnWriteArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners; + private CopyOnWriteArrayList<OnGlobalLayoutListener> mOnGlobalLayoutListeners; + private CopyOnWriteArrayList<OnPreDrawListener> mOnPreDrawListeners; + private CopyOnWriteArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners; + private CopyOnWriteArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners; + private CopyOnWriteArrayList<OnScrollChangedListener> mOnScrollChangedListeners; private boolean mAlive = true; @@ -283,7 +283,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnGlobalFocusListeners == null) { - mOnGlobalFocusListeners = new ArrayList<OnGlobalFocusChangeListener>(); + mOnGlobalFocusListeners = new CopyOnWriteArrayList<OnGlobalFocusChangeListener>(); } mOnGlobalFocusListeners.add(listener); @@ -318,7 +318,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnGlobalLayoutListeners == null) { - mOnGlobalLayoutListeners = new ArrayList<OnGlobalLayoutListener>(); + mOnGlobalLayoutListeners = new CopyOnWriteArrayList<OnGlobalLayoutListener>(); } mOnGlobalLayoutListeners.add(listener); @@ -352,7 +352,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnPreDrawListeners == null) { - mOnPreDrawListeners = new ArrayList<OnPreDrawListener>(); + mOnPreDrawListeners = new CopyOnWriteArrayList<OnPreDrawListener>(); } mOnPreDrawListeners.add(listener); @@ -388,7 +388,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnScrollChangedListeners == null) { - mOnScrollChangedListeners = new ArrayList<OnScrollChangedListener>(); + mOnScrollChangedListeners = new CopyOnWriteArrayList<OnScrollChangedListener>(); } mOnScrollChangedListeners.add(listener); @@ -424,7 +424,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnTouchModeChangeListeners == null) { - mOnTouchModeChangeListeners = new ArrayList<OnTouchModeChangeListener>(); + mOnTouchModeChangeListeners = new CopyOnWriteArrayList<OnTouchModeChangeListener>(); } mOnTouchModeChangeListeners.add(listener); @@ -460,7 +460,8 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnComputeInternalInsetsListeners == null) { - mOnComputeInternalInsetsListeners = new ArrayList<OnComputeInternalInsetsListener>(); + mOnComputeInternalInsetsListeners = + new CopyOnWriteArrayList<OnComputeInternalInsetsListener>(); } mOnComputeInternalInsetsListeners.add(listener); @@ -518,11 +519,14 @@ public final class ViewTreeObserver { * Notifies registered listeners that focus has changed. */ final void dispatchOnGlobalFocusChange(View oldFocus, View newFocus) { - final ArrayList<OnGlobalFocusChangeListener> globaFocusListeners = mOnGlobalFocusListeners; - if (globaFocusListeners != null) { - final int count = globaFocusListeners.size(); - for (int i = count - 1; i >= 0; i--) { - globaFocusListeners.get(i).onGlobalFocusChanged(oldFocus, newFocus); + // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to + // perform the dispatching. The iterator is a safe guard against listeners that + // could mutate the list by calling the various add/remove methods. This prevents + // the array from being modified while we iterate it. + final CopyOnWriteArrayList<OnGlobalFocusChangeListener> listeners = mOnGlobalFocusListeners; + if (listeners != null) { + for (OnGlobalFocusChangeListener listener : listeners) { + listener.onGlobalFocusChanged(oldFocus, newFocus); } } } @@ -533,11 +537,14 @@ public final class ViewTreeObserver { * not attached to a Window or in the GONE state. */ public final void dispatchOnGlobalLayout() { - final ArrayList<OnGlobalLayoutListener> globaLayoutListeners = mOnGlobalLayoutListeners; - if (globaLayoutListeners != null) { - final int count = globaLayoutListeners.size(); - for (int i = count - 1; i >= 0; i--) { - globaLayoutListeners.get(i).onGlobalLayout(); + // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to + // perform the dispatching. The iterator is a safe guard against listeners that + // could mutate the list by calling the various add/remove methods. This prevents + // the array from being modified while we iterate it. + final CopyOnWriteArrayList<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners; + if (listeners != null) { + for (OnGlobalLayoutListener listener : listeners) { + listener.onGlobalLayout(); } } } @@ -551,12 +558,15 @@ public final class ViewTreeObserver { * @return True if the current draw should be canceled and resceduled, false otherwise. */ public final boolean dispatchOnPreDraw() { + // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to + // perform the dispatching. The iterator is a safe guard against listeners that + // could mutate the list by calling the various add/remove methods. This prevents + // the array from being modified while we iterate it. boolean cancelDraw = false; - final ArrayList<OnPreDrawListener> preDrawListeners = mOnPreDrawListeners; - if (preDrawListeners != null) { - final int count = preDrawListeners.size(); - for (int i = count - 1; i >= 0; i--) { - cancelDraw |= !preDrawListeners.get(i).onPreDraw(); + final CopyOnWriteArrayList<OnPreDrawListener> listeners = mOnPreDrawListeners; + if (listeners != null) { + for (OnPreDrawListener listener : listeners) { + cancelDraw |= !listener.onPreDraw(); } } return cancelDraw; @@ -568,11 +578,15 @@ public final class ViewTreeObserver { * @param inTouchMode True if the touch mode is now enabled, false otherwise. */ final void dispatchOnTouchModeChanged(boolean inTouchMode) { - final ArrayList<OnTouchModeChangeListener> touchModeListeners = mOnTouchModeChangeListeners; - if (touchModeListeners != null) { - final int count = touchModeListeners.size(); - for (int i = count - 1; i >= 0; i--) { - touchModeListeners.get(i).onTouchModeChanged(inTouchMode); + // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to + // perform the dispatching. The iterator is a safe guard against listeners that + // could mutate the list by calling the various add/remove methods. This prevents + // the array from being modified while we iterate it. + final CopyOnWriteArrayList<OnTouchModeChangeListener> listeners = + mOnTouchModeChangeListeners; + if (listeners != null) { + for (OnTouchModeChangeListener listener : listeners) { + listener.onTouchModeChanged(inTouchMode); } } } @@ -581,11 +595,14 @@ public final class ViewTreeObserver { * Notifies registered listeners that something has scrolled. */ final void dispatchOnScrollChanged() { - final ArrayList<OnScrollChangedListener> listeners = mOnScrollChangedListeners; - + // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to + // perform the dispatching. The iterator is a safe guard against listeners that + // could mutate the list by calling the various add/remove methods. This prevents + // the array from being modified while we iterate it. + final CopyOnWriteArrayList<OnScrollChangedListener> listeners = mOnScrollChangedListeners; if (listeners != null) { - for (OnScrollChangedListener scl : mOnScrollChangedListeners) { - scl.onScrollChanged(); + for (OnScrollChangedListener listener : listeners) { + listener.onScrollChanged(); } } } @@ -594,7 +611,8 @@ public final class ViewTreeObserver { * Returns whether there are listeners for computing internal insets. */ final boolean hasComputeInternalInsetsListeners() { - final ArrayList<OnComputeInternalInsetsListener> listeners = mOnComputeInternalInsetsListeners; + final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners = + mOnComputeInternalInsetsListeners; return (listeners != null && listeners.size() > 0); } @@ -602,11 +620,15 @@ public final class ViewTreeObserver { * Calls all listeners to compute the current insets. */ final void dispatchOnComputeInternalInsets(InternalInsetsInfo inoutInfo) { - final ArrayList<OnComputeInternalInsetsListener> listeners = mOnComputeInternalInsetsListeners; + // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to + // perform the dispatching. The iterator is a safe guard against listeners that + // could mutate the list by calling the various add/remove methods. This prevents + // the array from being modified while we iterate it. + final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners = + mOnComputeInternalInsetsListeners; if (listeners != null) { - final int count = listeners.size(); - for (int i = count - 1; i >= 0; i--) { - listeners.get(i).onComputeInternalInsets(inoutInfo); + for (OnComputeInternalInsetsListener listener : listeners) { + listener.onComputeInternalInsets(inoutInfo); } } } diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java index b00e565..c718bac 100644 --- a/core/java/android/view/inputmethod/EditorInfo.java +++ b/core/java/android/view/inputmethod/EditorInfo.java @@ -78,12 +78,37 @@ public class EditorInfo implements InputType, Parcelable { public static final int IME_ACTION_DONE = 0x00000006; /** + * 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. + */ + 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. + */ + 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 the same as a "enter" key. Typically this is + * 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. + * 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; diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java index dcf68cd..4528b73 100644 --- a/core/java/android/webkit/CacheManager.java +++ b/core/java/android/webkit/CacheManager.java @@ -282,9 +282,7 @@ public final class CacheManager { CacheResult result = mDataBase.getCache(url); if (result != null) { if (result.contentLength == 0) { - if (result.httpStatusCode != 301 - && result.httpStatusCode != 302 - && result.httpStatusCode != 307) { + if (!checkCacheRedirect(result.httpStatusCode)) { // this should not happen. If it does, remove it. mDataBase.removeCache(url); return null; @@ -350,6 +348,17 @@ public final class CacheManager { return null; } + // according to the rfc 2616, the 303 response MUST NOT be cached. + if (statusCode == 303) { + return null; + } + + // like the other browsers, do not cache redirects containing a cookie + // header. + if (checkCacheRedirect(statusCode) && !headers.getSetCookie().isEmpty()) { + return null; + } + CacheResult ret = parseHeaders(statusCode, headers, mimeType); if (ret != null) { setupFiles(url, ret); @@ -395,9 +404,7 @@ public final class CacheManager { } cacheRet.contentLength = cacheRet.outFile.length(); - if (cacheRet.httpStatusCode == 301 - || cacheRet.httpStatusCode == 302 - || cacheRet.httpStatusCode == 307) { + if (checkCacheRedirect(cacheRet.httpStatusCode)) { // location is in database, no need to keep the file cacheRet.contentLength = 0; cacheRet.localPath = new String(); @@ -471,6 +478,15 @@ public final class CacheManager { } } + private static boolean checkCacheRedirect(int statusCode) { + if (statusCode == 301 || statusCode == 302 || statusCode == 307) { + // as 303 can't be cached, we do not return true + return true; + } else { + return false; + } + } + @SuppressWarnings("deprecation") private static void setupFiles(String url, CacheResult cacheRet) { if (true) { diff --git a/core/java/android/webkit/HttpAuthHandler.java b/core/java/android/webkit/HttpAuthHandler.java index 48b9eec..84dc9f0 100644 --- a/core/java/android/webkit/HttpAuthHandler.java +++ b/core/java/android/webkit/HttpAuthHandler.java @@ -80,8 +80,7 @@ public class HttpAuthHandler extends Handler { break; case AUTH_CANCEL: - - mNetwork.resetHandlersAndStopLoading(loader.getFrame()); + loader.handleAuthResponse(null, null); break; } @@ -126,24 +125,6 @@ public class HttpAuthHandler extends Handler { } /** - * Resets the HTTP-authentication request handler, removes - * all loaders that share the same BrowserFrame - * - * @param frame The browser frame - */ - /* package */ void reset(BrowserFrame frame) { - synchronized (mLoaderQueue) { - ListIterator<LoadListener> i = mLoaderQueue.listIterator(0); - while (i.hasNext()) { - LoadListener loader = i.next(); - if (frame == loader.getFrame()) { - i.remove(); - } - } - } - } - - /** * Enqueues the loader, if the loader is the only element * in the queue, starts processing the loader * diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java index f9fb0b0..c64200c 100644 --- a/core/java/android/webkit/LoadListener.java +++ b/core/java/android/webkit/LoadListener.java @@ -377,10 +377,6 @@ class LoadListener extends Handler implements EventHandler { } } - // if there is buffered data, commit them in the end - boolean needToCommit = mAuthHeader != null && !mustAuthenticate - && mNativeLoader != 0 && !mDataBuilder.isEmpty(); - // it is only here that we can reset the last mAuthHeader object // (if existed) and start a new one!!! mAuthHeader = null; @@ -415,10 +411,6 @@ class LoadListener extends Handler implements EventHandler { } } commitHeadersCheckRedirect(); - - if (needToCommit) { - commitLoad(); - } } /** @@ -452,6 +444,8 @@ class LoadListener extends Handler implements EventHandler { status.put("minor", minorVersion); status.put("code", code); status.put("reason", reasonPhrase); + // New status means new data. Clear the old. + mDataBuilder.clear(); sendMessageInternal(obtainMessage(MSG_STATUS, status)); } @@ -613,7 +607,6 @@ class LoadListener extends Handler implements EventHandler { // ask for it, so make sure we have a valid CacheLoader // before calling it. if (mCacheLoader != null) { - detachRequestHandle(); mCacheLoader.load(); if (Config.LOGV) { Log.v(LOGTAG, "LoadListener cache load url=" + url()); @@ -738,10 +731,16 @@ class LoadListener extends Handler implements EventHandler { if (mRequestHandle != null) { mRequestHandle.handleSslErrorResponse(proceed); } + if (!proceed) { + // Commit whatever data we have and tear down the loader. + commitLoad(); + tearDown(); + } } /** - * Uses user-supplied credentials to restar a request. + * Uses user-supplied credentials to restart a request. If the credentials + * are null, cancel the request. */ void handleAuthResponse(String username, String password) { if (Config.LOGV) { @@ -780,6 +779,10 @@ class LoadListener extends Handler implements EventHandler { } } } + } else { + // Commit whatever data we have and tear down the loader. + commitLoad(); + tearDown(); } } @@ -944,13 +947,12 @@ class LoadListener extends Handler implements EventHandler { * @return native response pointer */ private int createNativeResponse() { - // The reason we change HTTP_NOT_MODIFIED to HTTP_OK is because we know - // that WebCore never sends the if-modified-since header. Our - // CacheManager does it for us. If the server responds with a 304, then - // we treat it like it was a 200 code and proceed with loading the file - // from the cache. - int statusCode = mStatusCode == HTTP_NOT_MODIFIED - ? HTTP_OK : mStatusCode; + // If WebCore sends if-modified-since, mCacheLoader is null. If + // CacheManager sends it, mCacheLoader is not null. In this case, if the + // server responds with a 304, then we treat it like it was a 200 code + // and proceed with loading the file from the cache. + int statusCode = (mStatusCode == HTTP_NOT_MODIFIED && + mCacheLoader != null) ? HTTP_OK : mStatusCode; // pass content-type content-length and content-encoding final int nativeResponse = nativeCreateResponse( mUrl, statusCode, mStatusText, @@ -1181,8 +1183,6 @@ class LoadListener extends Handler implements EventHandler { // sync. Add 1 to account for the current redirect. mCacheRedirectCount = mRequestHandle.getRedirectCount() + 1; } - // Clear the buffered data since the redirect is valid. - mDataBuilder.clear(); } else { commitHeaders(); commitLoad(); @@ -1197,9 +1197,10 @@ class LoadListener extends Handler implements EventHandler { /** * Parses the content-type header. + * The first part only allows '-' if it follows x or X. */ private static final Pattern CONTENT_TYPE_PATTERN = - Pattern.compile("^([a-zA-Z\\*]+/[\\w\\+\\*-]+[\\.[\\w\\+-]+]*)$"); + Pattern.compile("^((?:[xX]-)?[a-zA-Z\\*]+/[\\w\\+\\*-]+[\\.[\\w\\+-]+]*)$"); private void parseContentTypeHeader(String contentType) { if (Config.LOGV) { diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java index c9cc208..85c2275 100644 --- a/core/java/android/webkit/MimeTypeMap.java +++ b/core/java/android/webkit/MimeTypeMap.java @@ -496,6 +496,7 @@ public /* package */ class MimeTypeMap { sMimeTypeMap.loadEntry("video/x-msvideo", "avi", false); sMimeTypeMap.loadEntry("video/x-sgi-movie", "movie", false); sMimeTypeMap.loadEntry("x-conference/x-cooltalk", "ice", false); + sMimeTypeMap.loadEntry("x-epoc/x-sisx-app", "sisx", false); } return sMimeTypeMap; diff --git a/core/java/android/webkit/Network.java b/core/java/android/webkit/Network.java index 74622b3..6fa0775 100644 --- a/core/java/android/webkit/Network.java +++ b/core/java/android/webkit/Network.java @@ -261,24 +261,6 @@ class Network { } /** - * If we need to stop loading done in a handler (here, browser frame), we - * send a message to the handler to stop loading, and remove all loaders - * that share the same CallbackProxy in question from all local - * handlers (such as ssl-error and http-authentication handler). - * @param proxy The CallbackProxy responsible for cancelling the current - * load. - */ - public void resetHandlersAndStopLoading(BrowserFrame frame) { - if (Config.LOGV) { - Log.v(LOGTAG, "Network.resetHandlersAndStopLoading()"); - } - - frame.stopLoading(); - mSslErrorHandler.reset(frame); - mHttpAuthHandler.reset(frame); - } - - /** * Saves the state of network handlers (user SSL and HTTP-authentication * preferences). * @param outState The out-state to save (write) to. diff --git a/core/java/android/webkit/SslErrorHandler.java b/core/java/android/webkit/SslErrorHandler.java index 115434a..2e2fa12 100644 --- a/core/java/android/webkit/SslErrorHandler.java +++ b/core/java/android/webkit/SslErrorHandler.java @@ -118,20 +118,6 @@ public class SslErrorHandler extends Handler { } /** - * Resets the SSL error handler, removes all loaders that - * share the same BrowserFrame. - */ - /* package */ synchronized void reset(BrowserFrame frame) { - ListIterator<LoadListener> i = mLoaderQueue.listIterator(0); - while (i.hasNext()) { - LoadListener loader = i.next(); - if (frame == loader.getFrame()) { - i.remove(); - } - } - } - - /** * Handles SSL error(s) on the way up to the user. */ /* package */ synchronized void handleSslErrorRequest(LoadListener loader) { @@ -244,12 +230,8 @@ public class SslErrorHandler extends Handler { primary > mSslPrefTable.getInt(host)) { mSslPrefTable.putInt(host, new Integer(primary)); } - - loader.handleSslErrorResponse(proceed); - } else { - loader.handleSslErrorResponse(proceed); - mNetwork.resetHandlersAndStopLoading(loader.getFrame()); } + loader.handleSslErrorResponse(proceed); } } } diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 65544d4..025e6bb 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -153,6 +153,7 @@ public class WebSettings { private boolean mNeedInitialFocus = true; private boolean mNavDump = false; private boolean mSupportZoom = true; + private boolean mBuiltInZoomControls = false; private boolean mAllowFileAccess = true; // Class to handle messages before WebCore is ready. @@ -364,6 +365,20 @@ public class WebSettings { } /** + * Sets whether the zoom mechanism built into WebView is used. + */ + public void setBuiltInZoomControls(boolean enabled) { + mBuiltInZoomControls = enabled; + } + + /** + * Returns true if the zoom mechanism built into WebView is being used. + */ + public boolean getBuiltInZoomControls() { + return mBuiltInZoomControls; + } + + /** * Enable or disable file access within WebView. File access is enabled by * default. */ diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 753267f..3205820 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -56,17 +56,20 @@ import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewTreeObserver; +import android.view.animation.AlphaAnimation; import android.view.inputmethod.InputMethodManager; import android.webkit.TextDialog.AutoCompleteAdapter; import android.webkit.WebViewCore.EventHub; import android.widget.AbsoluteLayout; import android.widget.AdapterView; import android.widget.ArrayAdapter; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ListView; import android.widget.Scroller; import android.widget.Toast; import android.widget.ZoomButtonsController; +import android.widget.ZoomControls; import android.widget.AdapterView.OnItemClickListener; import java.io.File; @@ -85,6 +88,9 @@ import java.util.List; * It uses the WebKit rendering engine to display * web pages and includes methods to navigate forward and backward * through a history, zoom in and out, perform text searches and more.</p> + * <p>To enable the built-in zoom, set + * {@link #getSettings() WebSettings}.{@link WebSettings#setBuiltInZoomControls(boolean)} + * (introduced in API version 3). * <p>Note that, in order for your Activity to access the Internet and load web pages * in a WebView, you must add the <var>INTERNET</var> permissions to your * Android Manifest file:</p> @@ -106,6 +112,57 @@ public class WebView extends AbsoluteLayout static final boolean DEBUG = false; static final boolean LOGV_ENABLED = DEBUG ? Config.LOGD : Config.LOGV; + private class ExtendedZoomControls extends FrameLayout { + public ExtendedZoomControls(Context context, AttributeSet attrs) { + super(context, attrs); + LayoutInflater inflater = (LayoutInflater) + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(com.android.internal.R.layout.zoom_magnify, this, true); + mZoomControls = (ZoomControls) findViewById(com.android.internal.R.id.zoomControls); + mZoomMagnify = (ImageView) findViewById(com.android.internal.R.id.zoomMagnify); + } + + public void show(boolean showZoom, boolean canZoomOut) { + mZoomControls.setVisibility(showZoom ? View.VISIBLE : View.GONE); + mZoomMagnify.setVisibility(canZoomOut ? View.VISIBLE : View.GONE); + fade(View.VISIBLE, 0.0f, 1.0f); + } + + public void hide() { + fade(View.GONE, 1.0f, 0.0f); + } + + private void fade(int visibility, float startAlpha, float endAlpha) { + AlphaAnimation anim = new AlphaAnimation(startAlpha, endAlpha); + anim.setDuration(500); + startAnimation(anim); + setVisibility(visibility); + } + + public void setIsZoomMagnifyEnabled(boolean isEnabled) { + mZoomMagnify.setEnabled(isEnabled); + } + + public boolean hasFocus() { + return mZoomControls.hasFocus() || mZoomMagnify.hasFocus(); + } + + public void setOnZoomInClickListener(OnClickListener listener) { + mZoomControls.setOnZoomInClickListener(listener); + } + + public void setOnZoomOutClickListener(OnClickListener listener) { + mZoomControls.setOnZoomOutClickListener(listener); + } + + public void setOnZoomMagnifyClickListener(OnClickListener listener) { + mZoomMagnify.setOnClickListener(listener); + } + + ZoomControls mZoomControls; + ImageView mZoomMagnify; + } + /** * Transportation object for returning WebView across thread boundaries. */ @@ -232,6 +289,9 @@ public class WebView extends AbsoluteLayout private static final int LONG_PRESS_TIMEOUT = 1000; // needed to avoid flinging after a pause of no movement private static final int MIN_FLING_TIME = 250; + // The time that the Zoom Controls are visible before fading away + private static final long ZOOM_CONTROLS_TIMEOUT = + ViewConfiguration.getZoomControlsTimeout(); // The amount of content to overlap between two screens when going through // pages with the space bar, in pixels. private static final int PAGE_SCROLL_OVERLAP = 24; @@ -472,6 +532,10 @@ public class WebView extends AbsoluteLayout } } + // The View containing the zoom controls + private ExtendedZoomControls mZoomControls; + private Runnable mZoomControlRunnable; + private ZoomButtonsController mZoomButtonsController; private ImageView mZoomOverviewButton; private ImageView mZoomFitPageButton; @@ -484,11 +548,6 @@ public class WebView extends AbsoluteLayout private ZoomButtonsController.OnZoomListener mZoomListener = new ZoomButtonsController.OnZoomListener() { - public void onCenter(int x, int y) { - // Don't translate when the control is invoked, hence we do nothing - // in this callback - } - public void onVisibilityChanged(boolean visible) { if (visible) { switchOutDrawHistory(); @@ -582,10 +641,26 @@ public class WebView extends AbsoluteLayout } private void updateZoomButtonsEnabled() { - mZoomButtonsController.setZoomInEnabled(mActualScale < mMaxZoomScale); - mZoomButtonsController.setZoomOutEnabled(mActualScale > mMinZoomScale); - mZoomFitPageButton.setEnabled(mActualScale != 1); - mZoomOverviewButton.setEnabled(canZoomScrollOut()); + boolean canZoomIn = mActualScale < mMaxZoomScale; + boolean canZoomOut = mActualScale > mMinZoomScale; + if (!canZoomIn && !canZoomOut) { + // Hide the zoom in and out buttons, as well as the fit to page + // button, if the page cannot zoom + mZoomButtonsController.getZoomControls().setVisibility(View.GONE); + mZoomFitPageButton.setVisibility(View.GONE); + } else { + // Bring back the hidden zoom controls. + mZoomButtonsController.getZoomControls() + .setVisibility(View.VISIBLE); + mZoomFitPageButton.setVisibility(View.VISIBLE); + // Set each one individually, as a page may be able to zoom in + // or out. + mZoomButtonsController.setZoomInEnabled(canZoomIn); + mZoomButtonsController.setZoomOutEnabled(canZoomOut); + mZoomFitPageButton.setEnabled(mActualScale != 1); + } + mZoomOverviewButton.setVisibility(canZoomScrollOut() ? View.VISIBLE: + View.GONE); } private void init() { @@ -1332,7 +1407,13 @@ public class WebView extends AbsoluteLayout return; } clearTextEntry(); - mZoomButtonsController.setVisible(true); + if (getSettings().getBuiltInZoomControls()) { + mZoomButtonsController.setVisible(true); + } else { + mPrivateHandler.removeCallbacks(mZoomControlRunnable); + mPrivateHandler.postDelayed(mZoomControlRunnable, + ZOOM_CONTROLS_TIMEOUT); + } } /** @@ -2535,8 +2616,17 @@ public class WebView extends AbsoluteLayout private void startZoomScrollOut() { setHorizontalScrollBarEnabled(false); setVerticalScrollBarEnabled(false); - if (mZoomButtonsController.isVisible()) { - mZoomButtonsController.setVisible(false); + if (getSettings().getBuiltInZoomControls()) { + if (mZoomButtonsController.isVisible()) { + mZoomButtonsController.setVisible(false); + } + } else { + if (mZoomControlRunnable != null) { + mPrivateHandler.removeCallbacks(mZoomControlRunnable); + } + if (mZoomControls != null) { + mZoomControls.hide(); + } } int width = getViewWidth(); int height = getViewHeight(); @@ -3206,7 +3296,6 @@ public class WebView extends AbsoluteLayout // Clean up the zoom controller mZoomButtonsController.setVisible(false); - ZoomButtonsController.finishZoomTutorial(mContext, false); } // Implementation for OnHierarchyChangeListener @@ -3255,7 +3344,7 @@ public class WebView extends AbsoluteLayout // false for the first parameter } } else { - if (!mZoomButtonsController.isVisible()) { + if (getSettings().getBuiltInZoomControls() && !mZoomButtonsController.isVisible()) { /* * The zoom controls come in their own window, so our window * loses focus. Our policy is to not draw the focus ring if @@ -3527,7 +3616,9 @@ public class WebView extends AbsoluteLayout mWebViewCore .sendMessage(EventHub.SET_SNAP_ANCHOR, 0, 0); } - if (getSettings().supportZoom() + WebSettings settings = getSettings(); + if (settings.supportZoom() + && settings.getBuiltInZoomControls() && !mZoomButtonsController.isVisible() && (canZoomScrollOut() || mMinZoomScale < mMaxZoomScale)) { @@ -3594,6 +3685,21 @@ public class WebView extends AbsoluteLayout mLastTouchTime = eventTime; mUserScroll = true; } + + if (!getSettings().getBuiltInZoomControls()) { + boolean showPlusMinus = mMinZoomScale < mMaxZoomScale; + boolean showMagnify = canZoomScrollOut(); + if (mZoomControls != null && (showPlusMinus || showMagnify)) { + if (mZoomControls.getVisibility() == View.VISIBLE) { + mPrivateHandler.removeCallbacks(mZoomControlRunnable); + } else { + mZoomControls.show(showPlusMinus, showMagnify); + } + mPrivateHandler.postDelayed(mZoomControlRunnable, + ZOOM_CONTROLS_TIMEOUT); + } + } + if (done) { // return false to indicate that we can't pan out of the // view space @@ -4050,18 +4156,83 @@ public class WebView extends AbsoluteLayout } } - // TODO: deprecate /** * Returns a view containing zoom controls i.e. +/- buttons. The caller is * in charge of installing this view to the view hierarchy. This view will * become visible when the user starts scrolling via touch and fade away if * the user does not interact with it. * <p/> - * From 1.5, WebView change to use ZoomButtonsController. This will return - * an invisible dummy view for backwards compatibility. + * API version 3 introduces a built-in zoom mechanism that is shown + * automatically by the MapView. This is the preferred approach for + * showing the zoom UI. + * + * @deprecated The built-in zoom mechanism is preferred, see + * {@link WebSettings#setBuiltInZoomControls(boolean)}. */ + @Deprecated public View getZoomControls() { - return mZoomButtonsController.getDummyZoomControls(); + if (!getSettings().supportZoom()) { + Log.w(LOGTAG, "This WebView doesn't support zoom."); + return null; + } + if (mZoomControls == null) { + mZoomControls = createZoomControls(); + + /* + * need to be set to VISIBLE first so that getMeasuredHeight() in + * {@link #onSizeChanged()} can return the measured value for proper + * layout. + */ + mZoomControls.setVisibility(View.VISIBLE); + mZoomControlRunnable = new Runnable() { + public void run() { + + /* Don't dismiss the controls if the user has + * focus on them. Wait and check again later. + */ + if (!mZoomControls.hasFocus()) { + mZoomControls.hide(); + } else { + mPrivateHandler.removeCallbacks(mZoomControlRunnable); + mPrivateHandler.postDelayed(mZoomControlRunnable, + ZOOM_CONTROLS_TIMEOUT); + } + } + }; + } + return mZoomControls; + } + + private ExtendedZoomControls createZoomControls() { + ExtendedZoomControls zoomControls = new ExtendedZoomControls(mContext + , null); + zoomControls.setOnZoomInClickListener(new OnClickListener() { + public void onClick(View v) { + // reset time out + mPrivateHandler.removeCallbacks(mZoomControlRunnable); + mPrivateHandler.postDelayed(mZoomControlRunnable, + ZOOM_CONTROLS_TIMEOUT); + zoomIn(); + } + }); + zoomControls.setOnZoomOutClickListener(new OnClickListener() { + public void onClick(View v) { + // reset time out + mPrivateHandler.removeCallbacks(mZoomControlRunnable); + mPrivateHandler.postDelayed(mZoomControlRunnable, + ZOOM_CONTROLS_TIMEOUT); + zoomOut(); + } + }); + zoomControls.setOnZoomMagnifyClickListener(new OnClickListener() { + public void onClick(View v) { + mPrivateHandler.removeCallbacks(mZoomControlRunnable); + mPrivateHandler.postDelayed(mZoomControlRunnable, + ZOOM_CONTROLS_TIMEOUT); + zoomScrollOut(); + } + }); + return zoomControls; } /** @@ -4070,7 +4241,7 @@ public class WebView extends AbsoluteLayout * * @return The instance of {@link ZoomButtonsController} used by this class, * or null if it is unavailable. - * @hide pending API council + * @hide */ public ZoomButtonsController getZoomButtonsController() { return mZoomButtonsController; diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index bd4bba8..965d900 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -905,10 +905,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te ((Filterable) getAdapter()).getFilter() == null) { return false; } - final Context context = mContext; - final InputMethodManager inputManager = (InputMethodManager) - context.getSystemService(Context.INPUT_METHOD_SERVICE); - return !inputManager.isFullscreenMode(); + return true; } /** @@ -2904,7 +2901,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te KeyEvent forwardEvent = event; if (forwardEvent.getRepeatCount() > 0) { - forwardEvent = new KeyEvent(event, event.getEventTime(), 0); + forwardEvent = KeyEvent.changeTimeRepeat(event, event.getEventTime(), 0); } int action = event.getAction(); @@ -2967,6 +2964,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te // want to figure out why this is. mTextFilter.setRawInputType(EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_FILTER); + mTextFilter.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); mTextFilter.addTextChangedListener(this); p.setFocusable(false); p.setTouchable(false); diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java index 1d553f1..04cb8a0 100644 --- a/core/java/android/widget/AbsSeekBar.java +++ b/core/java/android/widget/AbsSeekBar.java @@ -164,7 +164,7 @@ public abstract class AbsSeekBar extends ProgressBar { void onProgressRefresh(float scale, boolean fromUser) { Drawable thumb = mThumb; if (thumb != null) { - setThumbPos(getWidth(), getHeight(), thumb, scale, Integer.MIN_VALUE); + setThumbPos(getWidth(), thumb, scale, Integer.MIN_VALUE); /* * Since we draw translated, the drawable's bounds that it signals * for invalidation won't be the actual bounds we want invalidated, @@ -189,7 +189,7 @@ public abstract class AbsSeekBar extends ProgressBar { if (thumbHeight > trackHeight) { if (thumb != null) { - setThumbPos(w, h, thumb, scale, 0); + setThumbPos(w, thumb, scale, 0); } int gapForCenteringTrack = (thumbHeight - trackHeight) / 2; if (d != null) { @@ -206,16 +206,15 @@ public abstract class AbsSeekBar extends ProgressBar { } int gap = (trackHeight - thumbHeight) / 2; if (thumb != null) { - setThumbPos(w, h, thumb, scale, gap); + setThumbPos(w, thumb, scale, gap); } } } /** * @param gap If set to {@link Integer#MIN_VALUE}, this will be ignored and - * the old vertical bounds will be used. */ - private void setThumbPos(int w, int h, Drawable thumb, float scale, int gap) { + private void setThumbPos(int w, Drawable thumb, float scale, int gap) { int available = w - mPaddingLeft - mPaddingRight; int thumbWidth = thumb.getIntrinsicWidth(); int thumbHeight = thumb.getIntrinsicHeight(); @@ -353,6 +352,12 @@ public abstract class AbsSeekBar extends ProgressBar { void onStopTrackingTouch() { } + /** + * Called when the user changes the seekbar's progress by using a key event. + */ + void onKeyChange() { + } + @Override public boolean onKeyDown(int keyCode, KeyEvent event) { int progress = getProgress(); @@ -361,11 +366,13 @@ public abstract class AbsSeekBar extends ProgressBar { case KeyEvent.KEYCODE_DPAD_LEFT: if (progress <= 0) break; setProgress(progress - mKeyProgressIncrement, true); + onKeyChange(); return true; case KeyEvent.KEYCODE_DPAD_RIGHT: if (progress >= getMax()) break; setProgress(progress + mKeyProgressIncrement, true); + onKeyChange(); return true; } diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java index 8aafee2..2bb716c 100644 --- a/core/java/android/widget/FrameLayout.java +++ b/core/java/android/widget/FrameLayout.java @@ -56,6 +56,7 @@ public class FrameLayout extends ViewGroup { private final Rect mSelfBounds = new Rect(); private final Rect mOverlayBounds = new Rect(); private int mForegroundGravity = Gravity.FILL; + private boolean mForegroundInPadding = true; public FrameLayout(Context context) { super(context); @@ -71,6 +72,9 @@ public class FrameLayout extends ViewGroup { TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.FrameLayout, defStyle, 0); + mForegroundGravity = a.getInt( + com.android.internal.R.styleable.FrameLayout_foregroundGravity, mForegroundGravity); + final Drawable d = a.getDrawable(com.android.internal.R.styleable.FrameLayout_foreground); if (d != null) { setForeground(d); @@ -80,8 +84,8 @@ public class FrameLayout extends ViewGroup { setMeasureAllChildren(true); } - mForegroundGravity = a.getInt(com.android.internal.R.styleable.FrameLayout_foregroundGravity, - mForegroundGravity); + mForegroundInPadding = a.getBoolean( + com.android.internal.R.styleable.FrameLayout_foregroundInsidePadding, true); a.recycle(); } @@ -105,6 +109,23 @@ public class FrameLayout extends ViewGroup { } mForegroundGravity = foregroundGravity; + + + if (mForegroundGravity == Gravity.FILL && mForeground != null) { + Rect padding = new Rect(); + if (mForeground.getPadding(padding)) { + mForegroundPaddingLeft = padding.left; + mForegroundPaddingTop = padding.top; + mForegroundPaddingRight = padding.right; + mForegroundPaddingBottom = padding.bottom; + } + } else { + mForegroundPaddingLeft = 0; + mForegroundPaddingTop = 0; + mForegroundPaddingRight = 0; + mForegroundPaddingBottom = 0; + } + requestLayout(); } } @@ -167,12 +188,14 @@ public class FrameLayout extends ViewGroup { if (drawable.isStateful()) { drawable.setState(getDrawableState()); } - Rect padding = new Rect(); - if (drawable.getPadding(padding)) { - mForegroundPaddingLeft = padding.left; - mForegroundPaddingTop = padding.top; - mForegroundPaddingRight = padding.right; - mForegroundPaddingBottom = padding.bottom; + if (mForegroundGravity == Gravity.FILL) { + Rect padding = new Rect(); + if (drawable.getPadding(padding)) { + mForegroundPaddingLeft = padding.left; + mForegroundPaddingTop = padding.top; + mForegroundPaddingRight = padding.right; + mForegroundPaddingBottom = padding.bottom; + } } } else { setWillNotDraw(true); @@ -309,10 +332,14 @@ public class FrameLayout extends ViewGroup { final Rect selfBounds = mSelfBounds; final Rect overlayBounds = mOverlayBounds; - selfBounds.set(0, 0, w, h); + if (mForegroundInPadding) { + selfBounds.set(0, 0, w, h); + } else { + selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom); + } + Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(), foreground.getIntrinsicHeight(), selfBounds, overlayBounds); - foreground.setBounds(overlayBounds); } } diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java index 227fb95..a2ec83f 100644 --- a/core/java/android/widget/MediaController.java +++ b/core/java/android/widget/MediaController.java @@ -405,6 +405,8 @@ public class MediaController extends FrameLayout { return super.dispatchKeyEvent(event); } else if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) { hide(); + + return true; } else { show(sDefaultTimeout); } diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index a4f729f..f864690 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -1125,17 +1125,16 @@ public class PopupWindow { } /** - * <p>Updates the position and the dimension of the popup window. Width and - * height can be set to -1 to update location only. Calling this function - * also updates the window with the current popup state as - * described for {@link #update()}.</p> + * <p>Updates the position and the dimension of the popup window. Calling this + * function also updates the window with the current popup state as described + * for {@link #update()}.</p> * * @param anchor the popup's anchor view * @param width the new width, can be -1 to ignore * @param height the new height, can be -1 to ignore */ public void update(View anchor, int width, int height) { - update(anchor, 0, 0, width, height); + update(anchor, false, 0, 0, true, width, height); } /** @@ -1153,31 +1152,44 @@ public class PopupWindow { * @param height the new height, can be -1 to ignore */ public void update(View anchor, int xoff, int yoff, int width, int height) { + update(anchor, true, xoff, yoff, true, width, height); + } + + private void update(View anchor, boolean updateLocation, int xoff, int yoff, + boolean updateDimension, int width, int height) { + if (!isShowing() || mContentView == null) { return; } WeakReference<View> oldAnchor = mAnchor; if (oldAnchor == null || oldAnchor.get() != anchor || - mAnchorXoff != xoff || mAnchorYoff != yoff) { + (updateLocation && (mAnchorXoff != xoff || mAnchorYoff != yoff))) { registerForScrollChanged(anchor, xoff, yoff); } WindowManager.LayoutParams p = (WindowManager.LayoutParams) mPopupView.getLayoutParams(); - if (width == -1) { - width = mPopupWidth; - } else { - mPopupWidth = width; + if (updateDimension) { + if (width == -1) { + width = mPopupWidth; + } else { + mPopupWidth = width; + } + if (height == -1) { + height = mPopupHeight; + } else { + mPopupHeight = height; + } } - if (height == -1) { - height = mPopupHeight; + + if (updateLocation) { + mAboveAnchor = findDropDownPosition(anchor, p, xoff, yoff); } else { - mPopupHeight = height; + mAboveAnchor = findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff); } - - mAboveAnchor = findDropDownPosition(anchor, p, xoff, yoff); + update(p.x, p.y, width, height); } diff --git a/core/java/android/widget/RatingBar.java b/core/java/android/widget/RatingBar.java index ad5ca07..1800c5a 100644 --- a/core/java/android/widget/RatingBar.java +++ b/core/java/android/widget/RatingBar.java @@ -296,7 +296,13 @@ public class RatingBar extends AbsSeekBar { dispatchRatingChange(true); } } - + + @Override + void onKeyChange() { + super.onKeyChange(); + dispatchRatingChange(true); + } + void dispatchRatingChange(boolean fromUser) { if (mOnRatingBarChangeListener != null) { mOnRatingBarChangeListener.onRatingChanged(this, getRating(), diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index 52c421c..c4f0abd 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -821,7 +821,10 @@ public class RelativeLayout extends ViewGroup { @ViewDebug.IntToString(from = CENTER_VERTICAL, to = "centerVertical"), @ViewDebug.IntToString(from = LEFT_OF, to = "leftOf"), @ViewDebug.IntToString(from = RIGHT_OF, to = "rightOf") - }, mapping = { @ViewDebug.IntToString(from = TRUE, to = "true") }) + }, mapping = { + @ViewDebug.IntToString(from = TRUE, to = "true"), + @ViewDebug.IntToString(from = 0, to = "NO_ID") + }) private int[] mRules = new int[VERB_COUNT]; private int mLeft, mTop, mRight, mBottom; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 7b62b50..136752b 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -224,7 +224,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private CharSequence mError; private boolean mErrorWasChanged; - private PopupWindow mPopup; + private ErrorPopup mPopup; /** * This flag is set if the TextView tries to display an error before it * is attached to the window (so its position is still unknown). @@ -3039,12 +3039,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return; } } - } - if (ict != null || !shouldAdvanceFocusOnEnter()) { + // This is the handling for some default action. // Note that for backwards compatibility we don't do this // default handling if explicit ime options have not been given, - // to instead turn this into the normal enter key codes that an + // instead turning this into the normal enter key codes that an // app may be expecting. if (actionCode == EditorInfo.IME_ACTION_NEXT) { View v = focusSearch(FOCUS_DOWN); @@ -3066,15 +3065,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } Handler h = getHandler(); - long eventTime = SystemClock.uptimeMillis(); - h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME, - new KeyEvent(eventTime, eventTime, - KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0, - KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE))); - h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME, - new KeyEvent(SystemClock.uptimeMillis(), eventTime, - KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0, - KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE))); + if (h != null) { + long eventTime = SystemClock.uptimeMillis(); + h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME, + new KeyEvent(eventTime, eventTime, + KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0, + KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE + | KeyEvent.FLAG_EDITOR_ACTION))); + h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME, + new KeyEvent(SystemClock.uptimeMillis(), eventTime, + KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0, + KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE + | KeyEvent.FLAG_EDITOR_ACTION))); + } } /** @@ -3222,25 +3225,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final TextView err = (TextView) inflater.inflate(com.android.internal.R.layout.textview_hint, null); - mPopup = new PopupWindow(err, 200, 50) { - private boolean mAbove = false; - - @Override - public void update(int x, int y, int w, int h, boolean force) { - super.update(x, y, w, h, force); - - boolean above = isAboveAnchor(); - if (above != mAbove) { - mAbove = above; - - if (above) { - err.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error_above); - } else { - err.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error); - } - } - } - }; + mPopup = new ErrorPopup(err, 200, 50); mPopup.setFocusable(false); // The user is entering text, so the input method is needed. We // don't want the popup to be displayed on top of it. @@ -3252,6 +3237,37 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener tv.setText(mError); mPopup.showAsDropDown(this, getErrorX(), getErrorY()); + mPopup.fixDirection(mPopup.isAboveAnchor()); + } + + private static class ErrorPopup extends PopupWindow { + private boolean mAbove = false; + private TextView mView; + + ErrorPopup(TextView v, int width, int height) { + super(v, width, height); + mView = v; + } + + void fixDirection(boolean above) { + mAbove = above; + + if (above) { + mView.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error_above); + } else { + mView.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error); + } + } + + @Override + public void update(int x, int y, int w, int h, boolean force) { + super.update(x, y, w, h, force); + + boolean above = isAboveAnchor(); + if (above != mAbove) { + fixDirection(above); + } + } } /** @@ -4001,7 +4017,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { - KeyEvent down = new KeyEvent(event, KeyEvent.ACTION_DOWN); + KeyEvent down = KeyEvent.changeAction(event, KeyEvent.ACTION_DOWN); int which = doKeyDown(keyCode, down, event); if (which == 0) { @@ -4020,7 +4036,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // of down and up events until we have done the complete repeatCount. // It would be nice if those interfaces had an onKeyMultiple() method, // but adding that is a more complicated change. - KeyEvent up = new KeyEvent(event, KeyEvent.ACTION_UP); + KeyEvent up = KeyEvent.changeAction(event, KeyEvent.ACTION_UP); if (which == 1) { mInput.onKeyUp(this, (Editable)mText, keyCode, up); while (--repeatCount > 0) { @@ -4069,19 +4085,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return false; } - private boolean isInterestingEnter(KeyEvent event) { - if ((event.getFlags() & KeyEvent.FLAG_SOFT_KEYBOARD) != 0 && - mInputContentType != null && - (mInputContentType.imeOptions & - EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) { - // If this enter key came from a soft keyboard, and the - // text editor has been configured to not do a default - // action for software enter keys, then we aren't interested. - return false; - } - return true; - } - private int doKeyDown(int keyCode, KeyEvent event, KeyEvent otherEvent) { if (!isEnabled()) { return 0; @@ -4089,18 +4092,37 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener switch (keyCode) { case KeyEvent.KEYCODE_ENTER: - if (!isInterestingEnter(event)) { - // Ignore enter key we aren't interested in. - return -1; - } - if ((event.getMetaState()&KeyEvent.META_ALT_ON) == 0 - && mInputContentType != null - && mInputContentType.onEditorActionListener != null) { - mInputContentType.enterDown = true; - // We are consuming the enter key for them. - return -1; + // If ALT modifier is held, then we always insert a + // newline character. + if ((event.getMetaState()&KeyEvent.META_ALT_ON) == 0) { + + // When mInputContentType is set, we know that we are + // running in a "modern" cupcake environment, so don't need + // to worry about the application trying to capture + // enter key events. + if (mInputContentType != null) { + + // If there is an action listener, given them a + // chance to consume the event. + if (mInputContentType.onEditorActionListener != null && + mInputContentType.onEditorActionListener.onEditorAction( + this, EditorInfo.IME_NULL, event)) { + mInputContentType.enterDown = true; + // We are consuming the enter key for them. + return -1; + } + } + + // If our editor should move focus when enter is pressed, or + // this is a generated event from an IME action button, then + // don't let it be inserted into the text. + if ((event.getFlags()&KeyEvent.FLAG_EDITOR_ACTION) != 0 + || shouldAdvanceFocusOnEnter()) { + return -1; + } } - // fall through... + break; + case KeyEvent.KEYCODE_DPAD_CENTER: if (shouldAdvanceFocusOnEnter()) { return 0; @@ -4215,7 +4237,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } - if (shouldAdvanceFocusOnEnter()) { + if ((event.getFlags()&KeyEvent.FLAG_EDITOR_ACTION) != 0 + || shouldAdvanceFocusOnEnter()) { /* * If there is a click listener, just call through to * super, which will invoke it. @@ -4243,7 +4266,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener super.onKeyUp(keyCode, event); return true; } else if ((event.getFlags() - & KeyEvent.FLAG_SOFT_KEYBOARD) != 0) { + & KeyEvent.FLAG_EDITOR_ACTION) != 0) { // No target for next focus, but make sure the IME // if this came from it. InputMethodManager imm = InputMethodManager.peekInstance(); @@ -4302,6 +4325,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_ENTER_ACTION; } } + if ((outAttrs.inputType & (InputType.TYPE_MASK_CLASS + | InputType.TYPE_TEXT_FLAG_MULTI_LINE)) + == (InputType.TYPE_CLASS_TEXT + | InputType.TYPE_TEXT_FLAG_MULTI_LINE)) { + // Multi-line text editors should always show an enter key. + outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_ENTER_ACTION; + } outAttrs.hintText = mHint; if (mText instanceof Editable) { InputConnection ic = new EditableInputConnection(this); diff --git a/core/java/android/widget/ZoomButton.java b/core/java/android/widget/ZoomButton.java index 0df919d..c5fa18c 100644 --- a/core/java/android/widget/ZoomButton.java +++ b/core/java/android/widget/ZoomButton.java @@ -19,15 +19,11 @@ package android.widget; import android.content.Context; import android.os.Handler; import android.util.AttributeSet; -import android.view.GestureDetector; -import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; -import android.view.GestureDetector.SimpleOnGestureListener; import android.view.View.OnLongClickListener; - public class ZoomButton extends ImageButton implements OnLongClickListener { private final Handler mHandler; @@ -39,7 +35,6 @@ public class ZoomButton extends ImageButton implements OnLongClickListener { } } }; - private final GestureDetector mGestureDetector; private long mZoomSpeed = 1000; private boolean mIsInLongpress; @@ -55,19 +50,11 @@ public class ZoomButton extends ImageButton implements OnLongClickListener { public ZoomButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mHandler = new Handler(); - mGestureDetector = new GestureDetector(context, new SimpleOnGestureListener() { - @Override - public void onLongPress(MotionEvent e) { - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - onLongClick(ZoomButton.this); - } - }); setOnLongClickListener(this); } @Override public boolean onTouchEvent(MotionEvent event) { - mGestureDetector.onTouchEvent(event); if ((event.getAction() == MotionEvent.ACTION_CANCEL) || (event.getAction() == MotionEvent.ACTION_UP)) { mIsInLongpress = false; diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java index 4daa419..d9fb78b 100644 --- a/core/java/android/widget/ZoomButtonsController.java +++ b/core/java/android/widget/ZoomButtonsController.java @@ -16,23 +16,15 @@ package android.widget; -import android.app.AlertDialog; -import android.app.Dialog; import android.content.BroadcastReceiver; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.graphics.Canvas; import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.Handler; import android.os.Message; -import android.os.SystemClock; -import android.provider.Settings; import android.util.Log; -import android.view.GestureDetector; import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -42,7 +34,6 @@ import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewRoot; -import android.view.Window; import android.view.WindowManager; import android.view.View.OnClickListener; import android.view.WindowManager.LayoutParams; @@ -51,29 +42,33 @@ import android.view.WindowManager.LayoutParams; * Implementation notes: * - The zoom controls are displayed in their own window. * (Easier for the client and better performance) - * - This window is not touchable, and by default is not focusable. - * - To make the buttons clickable, it attaches a OnTouchListener to the owner - * view and does the hit detection locally. + * - This window is never touchable, and by default is not focusable. + * Its rect is quite big (fills horizontally) but has empty space between the + * edges and center. Touches there should be given to the owner. Instead of + * having the window touchable and dispatching these empty touch events to the + * owner, we set the window to not touchable and steal events from owner + * via onTouchListener. + * - To make the buttons clickable, it attaches an OnTouchListener to the owner + * view and does the hit detection locally (attaches when visible, detaches when invisible). * - When it is focusable, it forwards uninteresting events to the owner view's * view hierarchy. */ /** * The {@link ZoomButtonsController} handles showing and hiding the zoom - * controls relative to an owner view. It also gives the client access to the - * zoom controls container, allowing for additional accessory buttons to be - * shown in the zoom controls window. + * controls and positioning it relative to an owner view. It also gives the + * client access to the zoom controls container, allowing for additional + * accessory buttons to be shown in the zoom controls window. * <p> - * Typical usage involves the client using the {@link GestureDetector} to - * forward events from - * {@link GestureDetector.OnDoubleTapListener#onDoubleTapEvent(MotionEvent)} to - * {@link #handleDoubleTapEvent(MotionEvent)}. Also, whenever the owner cannot - * be zoomed further, the client should update + * Typically, clients should call {@link #setVisible(boolean) setVisible(true)} + * on a touch down or move (no need to call {@link #setVisible(boolean) + * setVisible(false)} since it will time out on its own). Also, whenever the + * owner cannot be zoomed further, the client should update * {@link #setZoomInEnabled(boolean)} and {@link #setZoomOutEnabled(boolean)}. * <p> * If you are using this with a custom View, please call * {@link #setVisible(boolean) setVisible(false)} from the * {@link View#onDetachedFromWindow}. - * + * * @hide */ public class ZoomButtonsController implements View.OnTouchListener { @@ -88,6 +83,7 @@ public class ZoomButtonsController implements View.OnTouchListener { private Context mContext; private WindowManager mWindowManager; + private boolean mAutoDismissControls = true; /** * The view that is being zoomed by this zoom controller. @@ -118,35 +114,26 @@ public class ZoomButtonsController implements View.OnTouchListener { * The {@link #mTouchTargetView}'s location in window, set on touch down. */ private int[] mTouchTargetWindowLocation = new int[2]; + /** * If the zoom controller is dismissed but the user is still in a touch * interaction, we set this to true. This will ignore all touch events until * up/cancel, and then set the owner's touch listener to null. + * <p> + * Otherwise, the owner view would get mismatched events (i.e., touch move + * even though it never got the touch down.) */ private boolean mReleaseTouchListenerOnUp; - /** - * Whether we are currently in the double-tap gesture, with the second tap - * still being performed (i.e., we're waiting for the second tap's touch up). - */ - private boolean mIsSecondTapDown; - /** Whether the container has been added to the window manager. */ private boolean mIsVisible; private Rect mTempRect = new Rect(); private int[] mTempIntArray = new int[2]; - + private OnZoomListener mCallback; /** - * In 1.0, the ZoomControls were to be added to the UI by the client of - * WebView, MapView, etc. We didn't want apps to break, so we return a dummy - * view in place now. - */ - private InvisibleView mDummyZoomControls; - - /** * When showing the zoom, we add the view as a new window. However, there is * logic that needs to know the size of the zoom which is determined after * it's laid out. Therefore, we must post this logic onto the UI thread so @@ -170,12 +157,6 @@ public class ZoomButtonsController implements View.OnTouchListener { } }; - /** - * The setting name that tracks whether we've shown the zoom tutorial. - */ - private static final String SETTING_NAME_SHOWN_TUTORIAL = "shown_zoom_tutorial"; - private static Dialog sTutorialDialog; - /** When configuration changes, this is called after the UI thread is idle. */ private static final int MSG_POST_CONFIGURATION_CHANGED = 2; /** Used to delay the zoom controller dismissal. */ @@ -215,7 +196,7 @@ public class ZoomButtonsController implements View.OnTouchListener { /** * Constructor for the {@link ZoomButtonsController}. - * + * * @param ownerView The view that is being zoomed by the zoom controls. The * zoom controls will be displayed aligned with this view. */ @@ -227,13 +208,13 @@ public class ZoomButtonsController implements View.OnTouchListener { mTouchPaddingScaledSq = (int) (ZOOM_CONTROLS_TOUCH_PADDING * mContext.getResources().getDisplayMetrics().density); mTouchPaddingScaledSq *= mTouchPaddingScaledSq; - + mContainer = createContainer(); } /** * Whether to enable the zoom in control. - * + * * @param enabled Whether to enable the zoom in control. */ public void setZoomInEnabled(boolean enabled) { @@ -242,7 +223,7 @@ public class ZoomButtonsController implements View.OnTouchListener { /** * Whether to enable the zoom out control. - * + * * @param enabled Whether to enable the zoom out control. */ public void setZoomOutEnabled(boolean enabled) { @@ -251,7 +232,7 @@ public class ZoomButtonsController implements View.OnTouchListener { /** * Sets the delay between zoom callbacks as the user holds a zoom button. - * + * * @param speed The delay in milliseconds between zoom callbacks. */ public void setZoomSpeed(long speed) { @@ -264,7 +245,8 @@ public class ZoomButtonsController implements View.OnTouchListener { lp.gravity = Gravity.TOP | Gravity.LEFT; lp.flags = LayoutParams.FLAG_NOT_TOUCHABLE | LayoutParams.FLAG_NOT_FOCUSABLE | - LayoutParams.FLAG_LAYOUT_NO_LIMITS; + LayoutParams.FLAG_LAYOUT_NO_LIMITS | + LayoutParams.FLAG_ALT_FOCUSABLE_IM; lp.height = LayoutParams.WRAP_CONTENT; lp.width = LayoutParams.FILL_PARENT; lp.type = LayoutParams.TYPE_APPLICATION_PANEL; @@ -299,7 +281,7 @@ public class ZoomButtonsController implements View.OnTouchListener { /** * Sets the {@link OnZoomListener} listener that receives callbacks to zoom. - * + * * @param listener The listener that will be told to zoom. */ public void setOnZoomListener(OnZoomListener listener) { @@ -310,7 +292,7 @@ public class ZoomButtonsController implements View.OnTouchListener { * Sets whether the zoom controls should be focusable. If the controls are * focusable, then trackball and arrow key interactions are possible. * Otherwise, only touch interactions are possible. - * + * * @param focusable Whether the zoom controls should be focusable. */ public void setFocusable(boolean focusable) { @@ -327,8 +309,26 @@ public class ZoomButtonsController implements View.OnTouchListener { } /** + * Whether the zoom controls will be automatically dismissed after showing. + * + * @return Whether the zoom controls will be auto dismissed after showing. + */ + public boolean isAutoDismissed() { + return mAutoDismissControls; + } + + /** + * Sets whether the zoom controls will be automatically dismissed after + * showing. + */ + public void setAutoDismissed(boolean autoDismiss) { + if (mAutoDismissControls == autoDismiss) return; + mAutoDismissControls = autoDismiss; + } + + /** * Whether the zoom controls are visible to the user. - * + * * @return Whether the zoom controls are visible to the user. */ public boolean isVisible() { @@ -337,7 +337,7 @@ public class ZoomButtonsController implements View.OnTouchListener { /** * Sets whether the zoom controls should be visible to the user. - * + * * @param visible Whether the zoom controls should be visible to the user. */ public void setVisible(boolean visible) { @@ -419,7 +419,7 @@ public class ZoomButtonsController implements View.OnTouchListener { * <p> * The client can add other views to this container to link them with the * zoom controls. - * + * * @return The container of the zoom controls. It will be a layout that * respects the gravity of a child's layout parameters. */ @@ -427,43 +427,20 @@ public class ZoomButtonsController implements View.OnTouchListener { return mContainer; } - private void dismissControlsDelayed(int delay) { - mHandler.removeMessages(MSG_DISMISS_ZOOM_CONTROLS); - mHandler.sendEmptyMessageDelayed(MSG_DISMISS_ZOOM_CONTROLS, delay); - } - /** - * Should be called by the client for each event belonging to the second tap - * (the down, move, up, and/or cancel events). + * Gets the view for the zoom controls. * - * @param event The event belonging to the second tap. - * @return Whether the event was consumed. + * @return The zoom controls view. */ - public boolean handleDoubleTapEvent(MotionEvent event) { - int action = event.getAction(); + public View getZoomControls() { + return mControls; + } - if (action == MotionEvent.ACTION_DOWN) { - int x = (int) event.getX(); - int y = (int) event.getY(); - - /* - * This class will consume all events in the second tap (down, - * move(s), up). But, the owner already got the second tap's down, - * so cancel that. Do this before setVisible, since that call - * will set us as a touch listener. - */ - MotionEvent cancelEvent = MotionEvent.obtain(event.getDownTime(), - SystemClock.elapsedRealtime(), - MotionEvent.ACTION_CANCEL, 0, 0, 0); - mOwnerView.dispatchTouchEvent(cancelEvent); - cancelEvent.recycle(); - - setVisible(true); - centerPoint(x, y); - mIsSecondTapDown = true; + private void dismissControlsDelayed(int delay) { + if (mAutoDismissControls) { + mHandler.removeMessages(MSG_DISMISS_ZOOM_CONTROLS); + mHandler.sendEmptyMessageDelayed(MSG_DISMISS_ZOOM_CONTROLS, delay); } - - return true; } private void refreshPositioningVariables() { @@ -477,7 +454,7 @@ public class ZoomButtonsController implements View.OnTouchListener { mOwnerView.getLocationOnScreen(mOwnerViewRawLocation); mContainerRawLocation[0] = mOwnerViewRawLocation[0]; mContainerRawLocation[1] = mOwnerViewRawLocation[1] + containerOwnerYOffset; - + int[] ownerViewWindowLoc = mTempIntArray; mOwnerView.getLocationInWindow(ownerViewWindowLoc); @@ -488,39 +465,30 @@ public class ZoomButtonsController implements View.OnTouchListener { if (mIsVisible) { mWindowManager.updateViewLayout(mContainer, mContainerLayoutParams); } - - } - /** - * Centers the point (in owner view's coordinates). - */ - private void centerPoint(int x, int y) { - if (mCallback != null) { - mCallback.onCenter(x, y); - } } /* This will only be called when the container has focus. */ private boolean onContainerKey(KeyEvent event) { int keyCode = event.getKeyCode(); if (isInterestingKey(keyCode)) { - + if (keyCode == KeyEvent.KEYCODE_BACK) { setVisible(false); } else { dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); } - + // Let the container handle the key return false; - + } else { - + ViewRoot viewRoot = getOwnerViewRoot(); if (viewRoot != null) { viewRoot.dispatchKey(event); } - + // We gave the key to the owner, don't let the container handle this key return true; } @@ -540,13 +508,13 @@ public class ZoomButtonsController implements View.OnTouchListener { return false; } } - + private ViewRoot getOwnerViewRoot() { View rootViewOfOwner = mOwnerView.getRootView(); if (rootViewOfOwner == null) { return null; } - + ViewParent parentOfRootView = rootViewOfOwner.getParent(); if (parentOfRootView instanceof ViewRoot) { return (ViewRoot) parentOfRootView; @@ -562,13 +530,6 @@ public class ZoomButtonsController implements View.OnTouchListener { public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); - // Consume all events during the second-tap interaction (down, move, up/cancel) - boolean consumeEvent = mIsSecondTapDown; - if ((action == MotionEvent.ACTION_UP) || (action == MotionEvent.ACTION_CANCEL)) { - // The second tap can no longer be down - mIsSecondTapDown = false; - } - if (mReleaseTouchListenerOnUp) { // The controls were dismissed but we need to throw away all events until the up if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { @@ -609,18 +570,21 @@ public class ZoomButtonsController implements View.OnTouchListener { mOwnerViewRawLocation[1] - targetViewRawY); /* Disallow negative coordinates (which can occur due to * ZOOM_CONTROLS_TOUCH_PADDING) */ - if (containerEvent.getX() < 0) { - containerEvent.offsetLocation(-containerEvent.getX(), 0); + // These are floats because we need to potentially offset away this exact amount + float containerX = containerEvent.getX(); + float containerY = containerEvent.getY(); + if (containerX < 0 && containerX > -ZOOM_CONTROLS_TOUCH_PADDING) { + containerEvent.offsetLocation(-containerX, 0); } - if (containerEvent.getY() < 0) { - containerEvent.offsetLocation(0, -containerEvent.getY()); + if (containerY < 0 && containerY > -ZOOM_CONTROLS_TOUCH_PADDING) { + containerEvent.offsetLocation(0, -containerY); } boolean retValue = targetView.dispatchTouchEvent(containerEvent); containerEvent.recycle(); - return retValue || consumeEvent; + return retValue; } else { - return consumeEvent; + return false; } } @@ -646,7 +610,7 @@ public class ZoomButtonsController implements View.OnTouchListener { View closestChild = null; int closestChildDistanceSq = Integer.MAX_VALUE; - + for (int i = mContainer.getChildCount() - 1; i >= 0; i--) { View child = mContainer.getChildAt(i); if (child.getVisibility() != View.VISIBLE) { @@ -657,13 +621,23 @@ public class ZoomButtonsController implements View.OnTouchListener { if (frame.contains(containerCoordsX, containerCoordsY)) { return child; } - - int distanceX = Math.min(Math.abs(frame.left - containerCoordsX), + + int distanceX; + if (containerCoordsX >= frame.left && containerCoordsX <= frame.right) { + distanceX = 0; + } else { + distanceX = Math.min(Math.abs(frame.left - containerCoordsX), Math.abs(containerCoordsX - frame.right)); - int distanceY = Math.min(Math.abs(frame.top - containerCoordsY), - Math.abs(containerCoordsY - frame.bottom)); + } + int distanceY; + if (containerCoordsY >= frame.top && containerCoordsY <= frame.bottom) { + distanceY = 0; + } else { + distanceY = Math.min(Math.abs(frame.top - containerCoordsY), + Math.abs(containerCoordsY - frame.bottom)); + } int distanceSq = distanceX * distanceX + distanceY * distanceY; - + if ((distanceSq < mTouchPaddingScaledSq) && (distanceSq < closestChildDistanceSq)) { closestChild = child; @@ -679,130 +653,27 @@ public class ZoomButtonsController implements View.OnTouchListener { refreshPositioningVariables(); } - /* - * This is static so Activities can call this instead of the Views - * (Activities usually do not have a reference to the ZoomButtonsController - * instance.) - */ - /** - * Shows a "tutorial" (some text) to the user teaching her the new zoom - * invocation method. Must call from the main thread. - * <p> - * It checks the global system setting to ensure this has not been seen - * before. Furthermore, if the application does not have privilege to write - * to the system settings, it will store this bit locally in a shared - * preference. - * - * @hide This should only be used by our main apps--browser, maps, and - * gallery - */ - public static void showZoomTutorialOnce(Context context) { - - // TODO: remove this code, but to hit the weekend build, just never show - if (true) return; - - ContentResolver cr = context.getContentResolver(); - if (Settings.System.getInt(cr, SETTING_NAME_SHOWN_TUTORIAL, 0) == 1) { - return; - } - - SharedPreferences sp = context.getSharedPreferences("_zoom", Context.MODE_PRIVATE); - if (sp.getInt(SETTING_NAME_SHOWN_TUTORIAL, 0) == 1) { - return; - } - - if (sTutorialDialog != null && sTutorialDialog.isShowing()) { - sTutorialDialog.dismiss(); - } - - LayoutInflater layoutInflater = - (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - TextView textView = (TextView) layoutInflater.inflate( - com.android.internal.R.layout.alert_dialog_simple_text, null) - .findViewById(android.R.id.text1); - textView.setText(com.android.internal.R.string.tutorial_double_tap_to_zoom_message_short); - - sTutorialDialog = new AlertDialog.Builder(context) - .setView(textView) - .setIcon(0) - .create(); - - Window window = sTutorialDialog.getWindow(); - window.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); - window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND | - WindowManager.LayoutParams.FLAG_BLUR_BEHIND); - window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | - WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); - - sTutorialDialog.show(); - } - - /** @hide Should only be used by Android platform apps */ - public static void finishZoomTutorial(Context context, boolean userNotified) { - if (sTutorialDialog == null) return; - - sTutorialDialog.dismiss(); - sTutorialDialog = null; - - // Record that they have seen the tutorial - if (userNotified) { - try { - Settings.System.putInt(context.getContentResolver(), SETTING_NAME_SHOWN_TUTORIAL, - 1); - } catch (SecurityException e) { - /* - * The app does not have permission to clear this global flag, make - * sure the user does not see the message when he comes back to this - * same app at least. - */ - SharedPreferences sp = context.getSharedPreferences("_zoom", Context.MODE_PRIVATE); - sp.edit().putInt(SETTING_NAME_SHOWN_TUTORIAL, 1).commit(); - } - } - } - - /** @hide Should only be used by Android platform apps */ - public void finishZoomTutorial() { - finishZoomTutorial(mContext, true); - } - - /** @hide Should only be used only be WebView and MapView */ - public View getDummyZoomControls() { - if (mDummyZoomControls == null) { - mDummyZoomControls = new InvisibleView(mContext); - } - return mDummyZoomControls; - } - /** * Interface that will be called when the user performs an interaction that * triggers some action, for example zooming. */ public interface OnZoomListener { - /** - * Called when the given point should be centered. The point will be in - * owner view coordinates. - * - * @param x The x of the point. - * @param y The y of the point. - */ - void onCenter(int x, int y); - + /** * Called when the zoom controls' visibility changes. - * + * * @param visible Whether the zoom controls are visible. */ void onVisibilityChanged(boolean visible); - + /** * Called when the owner view needs to be zoomed. - * + * * @param zoomIn The direction of the zoom: true to zoom in, false to zoom out. */ void onZoom(boolean zoomIn); } - + private class Container extends FrameLayout { public Container(Context context) { super(context); @@ -820,29 +691,4 @@ public class ZoomButtonsController implements View.OnTouchListener { } } - /** - * An InvisibleView is an invisible, zero-sized View for backwards - * compatibility - */ - private final class InvisibleView extends View { - - private InvisibleView(Context context) { - super(context); - setVisibility(GONE); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(0, 0); - } - - @Override - public void draw(Canvas canvas) { - } - - @Override - protected void dispatchDraw(Canvas canvas) { - } - } - } diff --git a/core/java/android/widget/ZoomControls.java b/core/java/android/widget/ZoomControls.java index 84d8f0e..a12aee5 100644 --- a/core/java/android/widget/ZoomControls.java +++ b/core/java/android/widget/ZoomControls.java @@ -30,11 +30,6 @@ import com.android.internal.R; /** * The {@code ZoomControls} class displays a simple set of controls used for zooming and * provides callbacks to register for events. */ -// TODO: pending API council -// * <p> -// * Instead of using this directly, consider using the {@link ZoomButtonsController} which -// * handles displaying the zoom controls. -// */ @Widget public class ZoomControls extends LinearLayout { diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java index 5c44b2d..b330a18 100644 --- a/core/java/com/android/internal/app/AlertController.java +++ b/core/java/com/android/internal/app/AlertController.java @@ -361,11 +361,14 @@ public class AlertController { if (mView != null) { customPanel = (FrameLayout) mWindow.findViewById(R.id.customPanel); FrameLayout custom = (FrameLayout) mWindow.findViewById(R.id.custom); - custom.addView(mView, new LayoutParams(FILL_PARENT, WRAP_CONTENT)); + custom.addView(mView, new LayoutParams(FILL_PARENT, FILL_PARENT)); if (mViewSpacingSpecified) { custom.setPadding(mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight, mViewSpacingBottom); } + if (mListView != null) { + ((LinearLayout.LayoutParams) customPanel.getLayoutParams()).weight = 0; + } } else { mWindow.findViewById(R.id.customPanel).setVisibility(View.GONE); } @@ -456,7 +459,9 @@ public class AlertController { if (mListView != null) { contentPanel.removeView(mWindow.findViewById(R.id.scrollView)); - contentPanel.addView(mListView, new LinearLayout.LayoutParams(FILL_PARENT, WRAP_CONTENT)); + contentPanel.addView(mListView, + new LinearLayout.LayoutParams(FILL_PARENT, FILL_PARENT)); + contentPanel.setLayoutParams(new LinearLayout.LayoutParams(FILL_PARENT, 0, 1.0f)); } else { contentPanel.setVisibility(View.GONE); } diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index edda1d9..d259756 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -30,7 +30,15 @@ interface IBatteryStats { void noteScreenOff(); void notePhoneOn(); void notePhoneOff(); - void setOnBattery(boolean onBattery); + void noteWifiOn(); + void noteWifiOff(); + void noteBluetoothOn(); + void noteBluetoothOff(); + void noteFullWifiLockAcquired(int uid); + void noteFullWifiLockReleased(int uid); + void noteScanWifiLockAcquired(int uid); + void noteScanWifiLockReleased(int uid); + void setOnBattery(boolean onBattery, int level); long getAwakeTimeBattery(); long getAwakeTimePlugged(); } diff --git a/core/java/com/android/internal/app/RingtonePickerActivity.java b/core/java/com/android/internal/app/RingtonePickerActivity.java index 1f8e6f0..5a0fea3 100644 --- a/core/java/com/android/internal/app/RingtonePickerActivity.java +++ b/core/java/com/android/internal/app/RingtonePickerActivity.java @@ -247,9 +247,13 @@ public final class RingtonePickerActivity extends AlertActivity implements } else { setResult(RESULT_CANCELED); } - - mCursor.deactivate(); - + + getWindow().getDecorView().post(new Runnable() { + public void run() { + mCursor.deactivate(); + } + }); + finish(); } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 7eea8b7..b3ae0d6 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -47,7 +47,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 25; + private static final int VERSION = 27; private final File mFile; private final File mBackupFile; @@ -92,6 +92,12 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mPhoneOn; Timer mPhoneOnTimer; + boolean mWifiOn; + Timer mWifiOnTimer; + + boolean mBluetoothOn; + Timer mBluetoothOnTimer; + /** * These provide time bases that discount the time the device is plugged * in to power. @@ -106,6 +112,12 @@ public final class BatteryStatsImpl extends BatteryStats { long mUnpluggedBatteryUptime; long mUnpluggedBatteryRealtime; + /* + * These keep track of battery levels (1-100) at the last plug event and the last unplug event. + */ + int mUnpluggedStartLevel; + int mPluggedStartLevel; + long mLastWriteTime = 0; // Milliseconds // For debugging @@ -471,6 +483,62 @@ public final class BatteryStatsImpl extends BatteryStats { } } + public void noteWifiOnLocked() { + if (!mWifiOn) { + mWifiOn = true; + mWifiOnTimer.startRunningLocked(this); + } + } + + public void noteWifiOffLocked() { + if (mWifiOn) { + mWifiOn = false; + mWifiOnTimer.stopRunningLocked(this); + } + } + + public void noteBluetoothOnLocked() { + if (!mBluetoothOn) { + mBluetoothOn = true; + mBluetoothOnTimer.startRunningLocked(this); + } + } + + public void noteBluetoothOffLocked() { + if (mBluetoothOn) { + mBluetoothOn = false; + mBluetoothOnTimer.stopRunningLocked(this); + } + } + + public void noteFullWifiLockAcquiredLocked(int uid) { + Uid u = mUidStats.get(uid); + if (u != null) { + u.noteFullWifiLockAcquiredLocked(); + } + } + + public void noteFullWifiLockReleasedLocked(int uid) { + Uid u = mUidStats.get(uid); + if (u != null) { + u.noteFullWifiLockReleasedLocked(); + } + } + + public void noteScanWifiLockAcquiredLocked(int uid) { + Uid u = mUidStats.get(uid); + if (u != null) { + u.noteScanWifiLockAcquiredLocked(); + } + } + + public void noteScanWifiLockReleasedLocked(int uid) { + Uid u = mUidStats.get(uid); + if (u != null) { + u.noteScanWifiLockReleasedLocked(); + } + } + @Override public long getScreenOnTime(long batteryRealtime, int which) { return mScreenOnTimer.getTotalTime(batteryRealtime, which); } @@ -479,6 +547,14 @@ public final class BatteryStatsImpl extends BatteryStats { return mPhoneOnTimer.getTotalTime(batteryRealtime, which); } + @Override public long getWifiOnTime(long batteryRealtime, int which) { + return mWifiOnTimer.getTotalTime(batteryRealtime, which); + } + + @Override public long getBluetoothOnTime(long batteryRealtime, int which) { + return mBluetoothOnTimer.getTotalTime(batteryRealtime, which); + } + @Override public boolean getIsOnBattery() { return mOnBattery; } @@ -505,6 +581,12 @@ public final class BatteryStatsImpl extends BatteryStats { long mStartedTcpBytesReceived = -1; long mStartedTcpBytesSent = -1; + boolean mFullWifiLockOut; + Timer mFullWifiLockTimer; + + boolean mScanWifiLockOut; + Timer mScanWifiLockTimer; + /** * The statistics we have collected for this uid's wake locks. */ @@ -527,6 +609,8 @@ public final class BatteryStatsImpl extends BatteryStats { public Uid(int uid) { mUid = uid; + mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables); + mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables); } @Override @@ -586,6 +670,47 @@ public final class BatteryStatsImpl extends BatteryStats { } } + @Override + public void noteFullWifiLockAcquiredLocked() { + if (!mFullWifiLockOut) { + mFullWifiLockOut = true; + mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); + } + } + + @Override + public void noteFullWifiLockReleasedLocked() { + if (mFullWifiLockOut) { + mFullWifiLockOut = false; + mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); + } + } + + @Override + public void noteScanWifiLockAcquiredLocked() { + if (!mScanWifiLockOut) { + mScanWifiLockOut = true; + mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this); + } + } + + @Override + public void noteScanWifiLockReleasedLocked() { + if (mScanWifiLockOut) { + mScanWifiLockOut = false; + mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); + } + } + @Override + public long getFullWifiLockTime(long batteryRealtime, int which) { + return mFullWifiLockTimer.getTotalTime(batteryRealtime, which); + } + + @Override + public long getScanWifiLockTime(long batteryRealtime, int which) { + return mScanWifiLockTimer.getTotalTime(batteryRealtime, which); + } + public long computeCurrentTcpBytesSent() { return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0 ? (NetStat.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0); @@ -626,6 +751,8 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeLong(computeCurrentTcpBytesSent()); out.writeLong(mTcpBytesReceivedAtLastUnplug); out.writeLong(mTcpBytesSentAtLastUnplug); + mFullWifiLockTimer.writeToParcel(out, batteryRealtime); + mScanWifiLockTimer.writeToParcel(out, batteryRealtime); } void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { @@ -671,6 +798,10 @@ public final class BatteryStatsImpl extends BatteryStats { mCurrentTcpBytesSent = in.readLong(); mTcpBytesReceivedAtLastUnplug = in.readLong(); mTcpBytesSentAtLastUnplug = in.readLong(); + mFullWifiLockOut = false; + mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables, in); + mScanWifiLockOut = false; + mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables, in); } /** @@ -852,6 +983,9 @@ public final class BatteryStatsImpl extends BatteryStats { } void writeToParcelLocked(Parcel out) { + final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; + final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime); + out.writeLong(mUserTime); out.writeLong(mSystemTime); out.writeInt(mStarts); @@ -1462,6 +1596,8 @@ public final class BatteryStatsImpl extends BatteryStats { mStartCount++; mScreenOnTimer = new Timer(-1, null, mUnpluggables); mPhoneOnTimer = new Timer(-2, null, mUnpluggables); + mWifiOnTimer = new Timer(-3, null, mUnpluggables); + mBluetoothOnTimer = new Timer(-4, null, mUnpluggables); mOnBattery = mOnBatteryInternal = false; mTrackBatteryPastUptime = 0; mTrackBatteryPastRealtime = 0; @@ -1469,6 +1605,8 @@ public final class BatteryStatsImpl extends BatteryStats { mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000; mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart); mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart); + mUnpluggedStartLevel = 0; + mPluggedStartLevel = 0; } public BatteryStatsImpl(Parcel p) { @@ -1485,7 +1623,7 @@ public final class BatteryStatsImpl extends BatteryStats { return mOnBattery; } - public void setOnBattery(boolean onBattery) { + public void setOnBattery(boolean onBattery, int level) { synchronized(this) { if (mOnBattery != onBattery) { mOnBattery = mOnBatteryInternal = onBattery; @@ -1498,10 +1636,12 @@ public final class BatteryStatsImpl extends BatteryStats { mTrackBatteryRealtimeStart = realtime; mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime); mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime); + mUnpluggedStartLevel = level; doUnplug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime); } else { mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart; mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart; + mPluggedStartLevel = level; doPlug(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime)); } if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) { @@ -1602,6 +1742,28 @@ public final class BatteryStatsImpl extends BatteryStats { public long getBatteryRealtime(long curTime) { return getBatteryRealtimeLocked(curTime); } + + @Override + public int getUnpluggedStartLevel() { + synchronized(this) { + return getUnluggedStartLevelLocked(); + } + } + + public int getUnluggedStartLevelLocked() { + return mUnpluggedStartLevel; + } + + @Override + public int getPluggedStartLevel() { + synchronized(this) { + return getPluggedStartLevelLocked(); + } + } + + public int getPluggedStartLevelLocked() { + return mPluggedStartLevel; + } /** * Retrieve the statistics object for a particular uid, creating if needed. @@ -1762,12 +1924,19 @@ public final class BatteryStatsImpl extends BatteryStats { mLastUptime = in.readLong(); mRealtime = in.readLong(); mLastRealtime = in.readLong(); + mUnpluggedStartLevel = in.readInt(); + mPluggedStartLevel = in.readInt(); + mStartCount++; mScreenOn = false; mScreenOnTimer.readSummaryFromParcelLocked(in); mPhoneOn = false; mPhoneOnTimer.readSummaryFromParcelLocked(in); + mWifiOn = false; + mWifiOnTimer.readSummaryFromParcelLocked(in); + mBluetoothOn = false; + mBluetoothOnTimer.readSummaryFromParcelLocked(in); final int NU = in.readInt(); for (int iu = 0; iu < NU; iu++) { @@ -1775,6 +1944,11 @@ public final class BatteryStatsImpl extends BatteryStats { Uid u = new Uid(uid); mUidStats.put(uid, u); + u.mFullWifiLockOut = false; + u.mFullWifiLockTimer.readSummaryFromParcelLocked(in); + u.mScanWifiLockOut = false; + u.mScanWifiLockTimer.readSummaryFromParcelLocked(in); + int NW = in.readInt(); for (int iw = 0; iw < NW; iw++) { String wlName = in.readString(); @@ -1857,15 +2031,23 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeLong(computeUptime(NOW_SYS, STATS_CURRENT)); out.writeLong(computeRealtime(NOWREAL_SYS, STATS_TOTAL)); out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT)); + out.writeInt(mUnpluggedStartLevel); + out.writeInt(mPluggedStartLevel); + mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); + mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); + mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); final int NU = mUidStats.size(); out.writeInt(NU); for (int iu = 0; iu < NU; iu++) { out.writeInt(mUidStats.keyAt(iu)); Uid u = mUidStats.valueAt(iu); + + u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); + u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); int NW = u.mWakelockStats.size(); out.writeInt(NW); @@ -1979,6 +2161,10 @@ public final class BatteryStatsImpl extends BatteryStats { mScreenOnTimer = new Timer(-1, null, mUnpluggables, in); mPhoneOn = false; mPhoneOnTimer = new Timer(-2, null, mUnpluggables, in); + mWifiOn = false; + mWifiOnTimer = new Timer(-2, null, mUnpluggables, in); + mBluetoothOn = false; + mBluetoothOnTimer = new Timer(-2, null, mUnpluggables, in); mUptime = in.readLong(); mUptimeStart = in.readLong(); mLastUptime = in.readLong(); @@ -1993,6 +2179,8 @@ public final class BatteryStatsImpl extends BatteryStats { mTrackBatteryRealtimeStart = in.readLong(); mUnpluggedBatteryUptime = in.readLong(); mUnpluggedBatteryRealtime = in.readLong(); + mUnpluggedStartLevel = in.readInt(); + mPluggedStartLevel = in.readInt(); mLastWriteTime = in.readLong(); mPartialTimers.clear(); @@ -2028,6 +2216,8 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeLong(mBatteryLastRealtime); mScreenOnTimer.writeToParcel(out, batteryRealtime); mPhoneOnTimer.writeToParcel(out, batteryRealtime); + mWifiOnTimer.writeToParcel(out, batteryRealtime); + mBluetoothOnTimer.writeToParcel(out, batteryRealtime); out.writeLong(mUptime); out.writeLong(mUptimeStart); out.writeLong(mLastUptime); @@ -2041,6 +2231,8 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeLong(mTrackBatteryRealtimeStart); out.writeLong(mUnpluggedBatteryUptime); out.writeLong(mUnpluggedBatteryRealtime); + out.writeInt(mUnpluggedStartLevel); + out.writeInt(mPluggedStartLevel); out.writeLong(mLastWriteTime); int size = mUidStats.size(); @@ -2070,6 +2262,10 @@ public final class BatteryStatsImpl extends BatteryStats { mScreenOnTimer.logState(); Log.i(TAG, "*** Phone timer:"); mPhoneOnTimer.logState(); + Log.i(TAG, "*** Wifi timer:"); + mWifiOnTimer.logState(); + Log.i(TAG, "*** Bluetooth timer:"); + mBluetoothOnTimer.logState(); } super.dumpLocked(pw); } diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java index 9e1f2ae..66e15c1 100644 --- a/core/java/com/android/internal/view/menu/IconMenuItemView.java +++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java @@ -28,6 +28,7 @@ import android.view.SoundEffectConstants; import android.view.View; import android.view.ViewDebug; import android.widget.TextView; +import android.text.Layout; /** * The item view for each item in the {@link IconMenuView}. @@ -236,6 +237,32 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie positionIcon(); } + @Override + protected void onTextChanged(CharSequence text, int start, int before, int after) { + super.onTextChanged(text, start, before, after); + + // our layout params depend on the length of the text + setLayoutParams(getTextAppropriateLayoutParams()); + } + + /** + * @return layout params appropriate for this view. If layout params already exist, it will + * augment them to be appropriate to the current text size. + */ + IconMenuView.LayoutParams getTextAppropriateLayoutParams() { + IconMenuView.LayoutParams lp = (IconMenuView.LayoutParams) getLayoutParams(); + if (lp == null) { + // Default layout parameters + lp = new IconMenuView.LayoutParams( + IconMenuView.LayoutParams.FILL_PARENT, IconMenuView.LayoutParams.FILL_PARENT); + } + + // Set the desired width of item + lp.desiredWidth = (int) Layout.getDesiredWidth(getText(), getPaint()); + + return lp; + } + /** * Positions the icon vertically (horizontal centering is taken care of by * the TextView's gravity). @@ -280,5 +307,5 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie public boolean showsIcon() { return true; } - + } diff --git a/core/java/com/android/internal/view/menu/IconMenuView.java b/core/java/com/android/internal/view/menu/IconMenuView.java index 781c608..6034a1e 100644 --- a/core/java/com/android/internal/view/menu/IconMenuView.java +++ b/core/java/com/android/internal/view/menu/IconMenuView.java @@ -26,7 +26,6 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; -import android.text.Layout; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.View; @@ -278,14 +277,7 @@ public final class IconMenuView extends ViewGroup implements ItemInvoker, MenuVi * Adds an IconMenuItemView to this icon menu view. * @param itemView The item's view to add */ - private void addItemView(IconMenuItemView itemView) { - LayoutParams lp = (LayoutParams) itemView.getLayoutParams(); - - if (lp == null) { - // Default layout parameters - lp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); - } - + private void addItemView(IconMenuItemView itemView) { // Set ourselves on the item view itemView.setIconMenuView(this); @@ -295,10 +287,7 @@ public final class IconMenuView extends ViewGroup implements ItemInvoker, MenuVi // This class is the invoker for all its item views itemView.setItemInvoker(this); - // Set the desired width of item - lp.desiredWidth = (int) Layout.getDesiredWidth(itemView.getText(), itemView.getPaint()); - - addView(itemView, lp); + addView(itemView, itemView.getTextAppropriateLayoutParams()); } /** diff --git a/core/jni/android_location_GpsLocationProvider.cpp b/core/jni/android_location_GpsLocationProvider.cpp index dee3fdd..f0b35e9 100644 --- a/core/jni/android_location_GpsLocationProvider.cpp +++ b/core/jni/android_location_GpsLocationProvider.cpp @@ -35,6 +35,7 @@ static jmethodID method_xtraDownloadRequest; static const GpsInterface* sGpsInterface = NULL; static const GpsXtraInterface* sGpsXtraInterface = NULL; +static const GpsSuplInterface* sGpsSuplInterface = NULL; // data written to by GPS callbacks static GpsLocation sGpsLocation; @@ -144,9 +145,10 @@ static void android_location_GpsLocationProvider_cleanup(JNIEnv* env, jobject ob sGpsInterface->cleanup(); } -static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj, jboolean singleFix, jint fixFrequency) +static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj, jint positionMode, + jboolean singleFix, jint fixFrequency) { - int result = sGpsInterface->set_position_mode(GPS_POSITION_MODE_STANDALONE, (singleFix ? 0 : fixFrequency)); + int result = sGpsInterface->set_position_mode(positionMode, (singleFix ? 0 : fixFrequency)); if (result) { return result; } @@ -267,6 +269,33 @@ static void android_location_GpsLocationProvider_inject_xtra_data(JNIEnv* env, j env->ReleaseByteArrayElements(data, bytes, 0); } +static void android_location_GpsLocationProvider_set_supl_server(JNIEnv* env, jobject obj, + jint addr, jint port) +{ + if (!sGpsSuplInterface) { + sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE); + } + if (sGpsSuplInterface) { + sGpsSuplInterface->set_server(addr, port); + } +} + +static void android_location_GpsLocationProvider_set_supl_apn(JNIEnv* env, jobject obj, jstring apn) +{ + if (!sGpsSuplInterface) { + sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE); + } + if (sGpsSuplInterface) { + if (apn == NULL) { + jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + return; + } + const char *apnStr = env->GetStringUTFChars(apn, NULL); + sGpsSuplInterface->set_apn(apnStr); + env->ReleaseStringUTFChars(apn, apnStr); + } +} + static JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native}, @@ -274,7 +303,7 @@ static JNINativeMethod sMethods[] = { {"native_init", "()Z", (void*)android_location_GpsLocationProvider_init}, {"native_disable", "()V", (void*)android_location_GpsLocationProvider_disable}, {"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup}, - {"native_start", "(ZI)Z", (void*)android_location_GpsLocationProvider_start}, + {"native_start", "(IZI)Z", (void*)android_location_GpsLocationProvider_start}, {"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop}, {"native_set_fix_frequency", "(I)V", (void*)android_location_GpsLocationProvider_set_fix_frequency}, {"native_delete_aiding_data", "(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data}, @@ -283,6 +312,8 @@ static JNINativeMethod sMethods[] = { {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time}, {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra}, {"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data}, + {"native_set_supl_server", "(II)V", (void*)android_location_GpsLocationProvider_set_supl_server}, + {"native_set_supl_apn", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_set_supl_apn}, }; int register_android_location_GpsLocationProvider(JNIEnv* env) diff --git a/core/jni/android_os_Hardware.cpp b/core/jni/android_os_Hardware.cpp index bc8af78..8007662 100644 --- a/core/jni/android_os_Hardware.cpp +++ b/core/jni/android_os_Hardware.cpp @@ -15,7 +15,6 @@ */ #include <hardware_legacy/flashlight.h> -#include <hardware_legacy/led.h> #include <hardware_legacy/power.h> #include <nativehelper/jni.h> @@ -24,12 +23,6 @@ namespace android { -static jboolean -setLedState(JNIEnv *env, jobject clazz, jint colorARGB, jint onMS, jint offMS) -{ - return set_led_state(colorARGB, onMS, offMS); -} - static jint getFlashlightEnabled(JNIEnv *env, jobject clazz) { @@ -48,24 +41,6 @@ enableCameraFlash(JNIEnv *env, jobject clazz, jint milliseconds) enable_camera_flash(milliseconds); } -static void -setScreenBacklight(JNIEnv *env, jobject clazz, jint brightness) -{ - set_light_brightness(SCREEN_LIGHT, brightness); -} - -static void -setKeyboardBacklight(JNIEnv *env, jobject clazz, jboolean on) -{ - set_light_brightness(KEYBOARD_LIGHT, (on ? 255 : 0)); -} - -static void -setButtonBacklight(JNIEnv *env, jobject clazz, jboolean on) -{ - set_light_brightness(BUTTON_LIGHT, (on ? 255 : 0)); -} - // ============================================================================ /* * JNI registration. @@ -73,13 +48,9 @@ setButtonBacklight(JNIEnv *env, jobject clazz, jboolean on) static JNINativeMethod g_methods[] = { /* name, signature, funcPtr */ - { "setLedState", "(III)I", (void*)setLedState }, { "getFlashlightEnabled", "()Z", (void*)getFlashlightEnabled }, { "setFlashlightEnabled", "(Z)V", (void*)setFlashlightEnabled }, { "enableCameraFlash", "(I)V", (void*)enableCameraFlash }, - { "setScreenBacklight", "(I)V", (void*)setScreenBacklight }, - { "setKeyboardBacklight", "(Z)V", (void*)setKeyboardBacklight }, - { "setButtonBacklight", "(Z)V", (void*)setButtonBacklight }, }; int register_android_os_Hardware(JNIEnv* env) diff --git a/core/jni/android_os_Power.cpp b/core/jni/android_os_Power.cpp index c2d75b1..df5edba 100644 --- a/core/jni/android_os_Power.cpp +++ b/core/jni/android_os_Power.cpp @@ -70,12 +70,6 @@ setLastUserActivityTimeout(JNIEnv *env, jobject clazz, jlong timeMS) } static int -setLightBrightness(JNIEnv *env, jobject clazz, jint mask, jint brightness) -{ - return set_light_brightness(mask, brightness); -} - -static int setScreenState(JNIEnv *env, jobject clazz, jboolean on) { return set_screen_state(on); @@ -109,7 +103,6 @@ static JNINativeMethod method_table[] = { { "acquireWakeLock", "(ILjava/lang/String;)V", (void*)acquireWakeLock }, { "releaseWakeLock", "(Ljava/lang/String;)V", (void*)releaseWakeLock }, { "setLastUserActivityTimeout", "(J)I", (void*)setLastUserActivityTimeout }, - { "setLightBrightness", "(II)I", (void*)setLightBrightness }, { "setScreenState", "(Z)I", (void*)setScreenState }, { "shutdown", "()V", (void*)android_os_Power_shutdown }, { "reboot", "(Ljava/lang/String;)V", (void*)android_os_Power_reboot }, diff --git a/core/res/assets/webkit/youtube.html b/core/res/assets/webkit/youtube.html index 5a40c1e..2aaaa15 100644 --- a/core/res/assets/webkit/youtube.html +++ b/core/res/assets/webkit/youtube.html @@ -43,7 +43,7 @@ <table height="100%" width="100%"> <tr> <td align="center" valign="middle" height="100%"> - <a id="url" href="youtube:VIDEO_ID" target="_top"> + <a id="url" href="vnd.youtube:VIDEO_ID" target="_top"> <img src="play.png" style="border:0px"/> </a> </td> diff --git a/core/res/res/anim/input_method_extract_enter.xml b/core/res/res/anim/input_method_extract_enter.xml new file mode 100644 index 0000000..96b049f --- /dev/null +++ b/core/res/res/anim/input_method_extract_enter.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/res/anim/fade_in.xml +** +** Copyright 2007, 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. +*/ +--> + +<alpha xmlns:android="http://schemas.android.com/apk/res/android" + android:interpolator="@anim/decelerate_interpolator" + android:fromAlpha="0.0" android:toAlpha="1.0" + android:duration="@android:integer/config_shortAnimTime" /> diff --git a/core/res/res/anim/input_method_extract_exit.xml b/core/res/res/anim/input_method_extract_exit.xml new file mode 100644 index 0000000..26db13f --- /dev/null +++ b/core/res/res/anim/input_method_extract_exit.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/res/anim/fade_out.xml +** +** Copyright 2007, 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. +*/ +--> + +<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/accelerate_interpolator" + android:fromAlpha="1.0" + android:toAlpha="0.0" + android:duration="@android:integer/config_shortAnimTime" +/> diff --git a/core/res/res/drawable-land/statusbar_background.png b/core/res/res/drawable-land/statusbar_background.png Binary files differindex 2a351a5..ef61e52 100644 --- a/core/res/res/drawable-land/statusbar_background.png +++ b/core/res/res/drawable-land/statusbar_background.png diff --git a/core/res/res/drawable/code_lock_left.9.png b/core/res/res/drawable/code_lock_left.9.png Binary files differindex a53264a..215dcc8 100644 --- a/core/res/res/drawable/code_lock_left.9.png +++ b/core/res/res/drawable/code_lock_left.9.png diff --git a/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.xml b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.xml new file mode 100644 index 0000000..2db3203 --- /dev/null +++ b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2008 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. +--> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" android:drawable="@drawable/ic_btn_square_browser_zoom_page_overview_disabled" /> + <item android:drawable="@drawable/ic_btn_square_browser_zoom_page_overview_normal" /> +</selector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview_disabled.png b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview_disabled.png Binary files differnew file mode 100644 index 0000000..859900a --- /dev/null +++ b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview_disabled.png diff --git a/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.png b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview_normal.png Binary files differindex 4e8ff35..4e8ff35 100644 --- a/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.png +++ b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview_normal.png diff --git a/core/res/res/drawable/status_bar_background.9.png b/core/res/res/drawable/status_bar_background.9.png Binary files differdeleted file mode 100644 index fd754a8..0000000 --- a/core/res/res/drawable/status_bar_background.9.png +++ /dev/null diff --git a/core/res/res/drawable/status_bar_background.png b/core/res/res/drawable/status_bar_background.png Binary files differnew file mode 100644 index 0000000..cd11166 --- /dev/null +++ b/core/res/res/drawable/status_bar_background.png diff --git a/core/res/res/drawable/status_bar_close_on.9.png b/core/res/res/drawable/status_bar_close_on.9.png Binary files differindex e91e4fa..9cbd9fe 100644 --- a/core/res/res/drawable/status_bar_close_on.9.png +++ b/core/res/res/drawable/status_bar_close_on.9.png diff --git a/core/res/res/drawable/status_bar_divider_shadow.9.png b/core/res/res/drawable/status_bar_header_background.9.png Binary files differindex ad58dbe..fa9a90c 100644 --- a/core/res/res/drawable/status_bar_divider_shadow.9.png +++ b/core/res/res/drawable/status_bar_header_background.9.png diff --git a/core/res/res/drawable/status_bar_item_background_normal.9.png b/core/res/res/drawable/status_bar_item_background_normal.9.png Binary files differindex 6b76740..b8e399d 100644 --- a/core/res/res/drawable/status_bar_item_background_normal.9.png +++ b/core/res/res/drawable/status_bar_item_background_normal.9.png diff --git a/core/res/res/drawable/statusbar_background.png b/core/res/res/drawable/statusbar_background.png Binary files differindex 2d8aa7a..204d76a 100644 --- a/core/res/res/drawable/statusbar_background.png +++ b/core/res/res/drawable/statusbar_background.png diff --git a/core/res/res/drawable/title_bar_portrait.9.png b/core/res/res/drawable/title_bar_portrait.9.png Binary files differnew file mode 100644 index 0000000..482d82e --- /dev/null +++ b/core/res/res/drawable/title_bar_portrait.9.png diff --git a/core/res/res/layout/always_use_checkbox.xml b/core/res/res/layout/always_use_checkbox.xml index 20fc403..5e6e388 100644 --- a/core/res/res/layout/always_use_checkbox.xml +++ b/core/res/res/layout/always_use_checkbox.xml @@ -16,7 +16,7 @@ <!-- Check box that is displayed in the activity resolver UI for the user to make their selection the preferred activity. --> -<RelativeLayout +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" @@ -27,7 +27,6 @@ android:id="@+id/alwaysUse" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_alignParentLeft="true" android:focusable="true" android:clickable="true" /> @@ -38,6 +37,5 @@ android:textAppearance="?android:attr/textAppearanceSmall" android:paddingLeft="36dip" android:visibility="gone" - android:layout_below="@id/alwaysUse" android:text="@string/clearDefaultHintMsg" /> -</RelativeLayout> +</LinearLayout> diff --git a/core/res/res/layout/input_method.xml b/core/res/res/layout/input_method.xml index a21bbe8..1a701e9 100644 --- a/core/res/res/layout/input_method.xml +++ b/core/res/res/layout/input_method.xml @@ -25,19 +25,28 @@ android:orientation="vertical" > - <FrameLayout android:id="@android:id/extractArea" - android:layout_width="fill_parent" - android:layout_height="0px" - android:layout_weight="1" - android:visibility="gone"> - </FrameLayout> - - <FrameLayout android:id="@android:id/candidatesArea" + <LinearLayout + android:id="@+id/fullscreenArea" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:visibility="invisible"> - </FrameLayout> - + android:orientation="vertical" + > + + <FrameLayout android:id="@android:id/extractArea" + android:layout_width="fill_parent" + android:layout_height="0px" + android:layout_weight="1" + android:visibility="gone"> + </FrameLayout> + + <FrameLayout android:id="@android:id/candidatesArea" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:visibility="invisible"> + </FrameLayout> + + </LinearLayout> + <FrameLayout android:id="@android:id/inputArea" android:layout_width="fill_parent" android:layout_height="wrap_content" diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml index ba1640a..d0388a6 100644 --- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml +++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml @@ -114,10 +114,10 @@ </FrameLayout> </LinearLayout> - <!--View + <View android:background="@android:drawable/code_lock_left" android:layout_width="2dip" - android:layout_height="fill_parent" /--> + android:layout_height="fill_parent" /> <!-- right side: lock pattern --> <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern" diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml index f09c422..59cd7a3 100644 --- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml +++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml @@ -53,18 +53,18 @@ android:textSize="18sp"/> </LinearLayout> - <!--View + <View android:background="@android:drawable/code_lock_top" android:layout_width="fill_parent" - android:layout_height="2dip" /--> + android:layout_height="2dip" /> <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern" android:layout_width="wrap_content" android:layout_height="wrap_content" /> - <!--View + <View android:background="@android:drawable/code_lock_bottom" android:layout_width="fill_parent" - android:layout_height="8dip" /--> + android:layout_height="8dip" /> <!-- footer --> <FrameLayout diff --git a/core/res/res/layout/screen_simple.xml b/core/res/res/layout/screen_simple.xml index 62e737a..df511c6 100644 --- a/core/res/res/layout/screen_simple.xml +++ b/core/res/res/layout/screen_simple.xml @@ -22,7 +22,8 @@ enabled. --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@android:id/content" - android:fitsSystemWindows="true"> -</FrameLayout> - + android:id="@android:id/content" + android:fitsSystemWindows="true" + android:foregroundInsidePadding="false" + android:foregroundGravity="fill_horizontal|top" + android:foreground="?android:attr/windowContentOverlay" />
\ No newline at end of file diff --git a/core/res/res/layout/status_bar.xml b/core/res/res/layout/status_bar.xml index 9a6b7e8..0bc0dac 100644 --- a/core/res/res/layout/status_bar.xml +++ b/core/res/res/layout/status_bar.xml @@ -97,7 +97,7 @@ android:gravity="center_vertical|left" android:paddingLeft="6px" android:paddingRight="6px" - android:textColor="#ff000000" + android:textColor="?android:attr/textColorPrimaryInverse" android:background="@drawable/statusbar_background" /> </com.android.server.status.StatusBarView> diff --git a/core/res/res/layout/status_bar_expanded.xml b/core/res/res/layout/status_bar_expanded.xml index a6a188e..fd9d26e 100644 --- a/core/res/res/layout/status_bar_expanded.xml +++ b/core/res/res/layout/status_bar_expanded.xml @@ -31,12 +31,13 @@ android:paddingTop="3dp" android:paddingBottom="5dp" android:paddingRight="3dp" - android:background="@drawable/status_bar_divider_shadow" + android:background="@drawable/status_bar_header_background" > <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" + android:layout_marginTop="1dp" android:layout_marginLeft="5dp" android:layout_gravity="center_vertical" android:paddingBottom="1dp" @@ -46,86 +47,99 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - android:textSize="18sp" - android:textStyle="bold" - android:textColor="#ff000000" + android:textAppearance="?android:attr/textAppearanceLarge" + android:textColor="?android:attr/textColorSecondaryInverse" + android:paddingLeft="4dp" /> <TextView android:id="@+id/spnLabel" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="18sp" - android:textStyle="bold" - android:textColor="#ff000000" - android:paddingBottom="1dp" + android:layout_gravity="center_vertical" + android:textAppearance="?android:attr/textAppearanceLarge" + android:textColor="?android:attr/textColorSecondaryInverse" + android:paddingLeft="4dp" /> </LinearLayout> <TextView android:id="@+id/clear_all_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" + android:layout_marginTop="4dp" + android:layout_marginBottom="1dp" android:textSize="14sp" android:textColor="#ff000000" android:text="@string/status_bar_clear_all_button" style="?android:attr/buttonStyle" + android:paddingLeft="15dp" + android:paddingRight="15dp" + android:background="@drawable/btn_default_small" /> </LinearLayout> - - <!-- This view has the same background as the tracking view. Normally it isn't shown, - except in the case where our copy of the close button is visible. That button is - translucent. Even though it moves up and down, it's only visible when it's aligned - at the bottom. - --> - <ScrollView - android:id="@+id/scroll" - android:layout_width="fill_parent" + <FrameLayout + android:layout_width="fill_parent" android:layout_height="wrap_content" - android:layout_weight="1" > - <com.android.server.status.NotificationLinearLayout - android:id="@+id/notificationLinearLayout" + <ScrollView + android:id="@+id/scroll" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" - android:orientation="vertical" + android:fadingEdge="none" > - - <TextView android:id="@+id/noNotificationsTitle" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:background="#ff888888" - android:paddingLeft="5dp" - android:textAppearance="@style/TextAppearance.StatusBarTitle" - android:text="@string/status_bar_no_notifications_title" - /> - - <TextView android:id="@+id/ongoingTitle" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:background="#ff888888" - android:paddingLeft="5dp" - android:textAppearance="@style/TextAppearance.StatusBarTitle" - android:text="@string/status_bar_ongoing_events_title" - /> - <LinearLayout android:id="@+id/ongoingItems" + <com.android.server.status.NotificationLinearLayout + android:id="@+id/notificationLinearLayout" android:layout_width="fill_parent" android:layout_height="wrap_content" + android:layout_weight="1" android:orientation="vertical" - /> + > + + <TextView android:id="@+id/noNotificationsTitle" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:background="@drawable/title_bar_portrait" + android:paddingLeft="5dp" + android:textAppearance="@style/TextAppearance.StatusBarTitle" + android:text="@string/status_bar_no_notifications_title" + /> - <TextView android:id="@+id/latestTitle" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:background="#ff888888" - android:paddingLeft="5dp" - android:textAppearance="@style/TextAppearance.StatusBarTitle" - android:text="@string/status_bar_latest_events_title" - /> - <LinearLayout android:id="@+id/latestItems" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - /> - </com.android.server.status.NotificationLinearLayout> - </ScrollView> + <TextView android:id="@+id/ongoingTitle" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:background="@drawable/title_bar_portrait" + android:paddingLeft="5dp" + android:textAppearance="@style/TextAppearance.StatusBarTitle" + android:text="@string/status_bar_ongoing_events_title" + /> + <LinearLayout android:id="@+id/ongoingItems" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + /> + + <TextView android:id="@+id/latestTitle" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:background="@drawable/title_bar_portrait" + android:paddingLeft="5dp" + android:textAppearance="@style/TextAppearance.StatusBarTitle" + android:text="@string/status_bar_latest_events_title" + /> + <LinearLayout android:id="@+id/latestItems" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + /> + </com.android.server.status.NotificationLinearLayout> + </ScrollView> + + <ImageView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:src="@drawable/title_bar_shadow" + android:scaleType="fitXY" + /> + + </FrameLayout> </com.android.server.status.ExpandedView> diff --git a/core/res/res/layout/status_bar_tracking.xml b/core/res/res/layout/status_bar_tracking.xml index 661ce86..aa3b733 100644 --- a/core/res/res/layout/status_bar_tracking.xml +++ b/core/res/res/layout/status_bar_tracking.xml @@ -20,13 +20,12 @@ android:visibility="gone" android:focusable="true" android:descendantFocusability="afterDescendants" - android:background="@drawable/status_bar_background" android:paddingBottom="0px" android:paddingLeft="0px" android:paddingRight="0px" > - <View + <com.android.server.status.TrackingPatternView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" @@ -37,11 +36,6 @@ android:layout_height="wrap_content" android:orientation="vertical" > - - <View - android:layout_width="fill_parent" - android:layout_height="5dp" - /> <ImageView android:layout_width="fill_parent" android:layout_height="wrap_content" diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 13aca371..27cefb0 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"Ve výchozím nastavení není identifikace volajícího omezena. Příští hovor: Neomezeno"</string> <string name="serviceNotProvisioned">"Služba není zřízena."</string> <string name="CLIRPermanent">"Nelze změnit nastavení identifikace volajícího."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Hlas"</string> <string name="serviceClassData">"Data"</string> <string name="serviceClassFAX">"FAX"</string> @@ -286,8 +296,10 @@ <string name="permdesc_locationUpdates">"Umožňuje povolit či zakázat aktualizace polohy prostřednictvím bezdrátového připojení. Aplikace toto nastavení obvykle nepoužívají."</string> <string name="permlab_checkinProperties">"přístup k vlastnostem Checkin"</string> <string name="permdesc_checkinProperties">"Umožňuje čtení i zápis vlastností nahraných službou Checkin. Běžné aplikace toto nastavení obvykle nevyužívají."</string> - <string name="permlab_bindGadget">"zvolit gadgety"</string> - <string name="permdesc_bindGadget">"Umožňuje aplikaci sdělit systému, které aplikace mohou použít které gadgety. Aplikace s tímto oprávněním mohou zpřístupnit osobní údaje jiným aplikacím. Není určeno pro normální aplikace."</string> + <!-- no translation found for permlab_bindGadget (776905339015863471) --> + <skip /> + <!-- no translation found for permdesc_bindGadget (2098697834497452046) --> + <skip /> <string name="permlab_modifyPhoneState">"změny stavu telefonu"</string> <string name="permdesc_modifyPhoneState">"Umožňuje aplikaci ovládat telefonní funkce zařízení. Aplikace s tímto oprávněním může přepínat sítě nebo zapnout či vypnout bezdrátové připojení telefonu bez vašeho svolení."</string> <string name="permlab_readPhoneState">"zjistit stav telefonu"</string> @@ -405,7 +417,8 @@ <string name="lockscreen_missing_sim_instructions">"Prosím vložte kartu SIM."</string> <string name="lockscreen_network_locked_message">"Síť je blokována"</string> <string name="lockscreen_sim_puk_locked_message">"Karta SIM je zablokována pomocí kódu PUK."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Prosím kontaktujte podporu zákazníků."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"Karta SIM je zablokována."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"Odblokování karty SIM..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"<xliff:g id="NUMBER_0">%d</xliff:g>krát jste nakreslili nesprávné bezpečnostní gesto. "\n\n"Opakujte prosím akci za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string> @@ -413,7 +426,8 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Sekundy zbývající do dalšího pokusu: <xliff:g id="NUMBER">%d</xliff:g>."</string> <string name="lockscreen_forgot_pattern_button_text">"Zapomněli jste gesto?"</string> <string name="lockscreen_glogin_too_many_attempts">"Gesta: Příliš mnoho pokusů"</string> - <string name="lockscreen_glogin_instructions">"Chcete-li telefon odemknout,"\n"přihlaste se pomocí svého účtu Google"</string> + <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) --> + <skip /> <string name="lockscreen_glogin_username_hint">"Uživatelské jméno (e-mail)"</string> <string name="lockscreen_glogin_password_hint">"Heslo"</string> <string name="lockscreen_glogin_submit_button">"Přihlásit se"</string> @@ -552,6 +566,8 @@ <string name="monthly">"Měsíčně"</string> <string name="yearly">"Ročně"</string> <string name="VideoView_error_title">"Video nelze přehrát"</string> + <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) --> + <skip /> <string name="VideoView_error_text_unknown">"Toto video bohužel nelze přehrát."</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"dop."</string> @@ -573,14 +589,14 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"poledne"</string> <string name="Noon">"Poledne"</string> <string name="midnight">"půlnoc"</string> <string name="Midnight">"Půlnoc"</string> <!-- no translation found for month_day (3693060561170538204) --> <skip /> - <!-- no translation found for month (1976700695144952053) --> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for month_year (2106203387378728384) --> @@ -616,7 +632,7 @@ <skip /> <!-- no translation found for abbrev_month_day (3156047263406783231) --> <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"neděle"</string> <string name="day_of_week_long_monday">"pondělí"</string> @@ -810,6 +826,8 @@ <skip /> <!-- no translation found for ime_action_next (3138843904009813834) --> <skip /> + <!-- no translation found for ime_action_done (8971516117910934605) --> + <skip /> <!-- no translation found for ime_action_default (2840921885558045721) --> <skip /> </resources> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index cda8cbc..8619084 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"Anrufer-ID ist standardmäßig nicht beschränkt. Nächster Anruf: Nicht beschränkt"</string> <string name="serviceNotProvisioned">"Dienst nicht eingerichtet."</string> <string name="CLIRPermanent">"Die Einstellung für die Anrufer-ID kann nicht geändert werden."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Sprachnotiz"</string> <string name="serviceClassData">"Daten"</string> <string name="serviceClassFAX">"FAX"</string> @@ -286,8 +296,10 @@ <string name="permdesc_locationUpdates">"Ermöglicht die Aktivierung/Deaktivierung der Radio-Benachrichtigungen über Standort-Updates. Nicht für normale Anwendungen vorgesehen."</string> <string name="permlab_checkinProperties">"Auf Check-In-Eigenschaften zugreifen"</string> <string name="permdesc_checkinProperties">"Ermöglicht den Schreib-/Lesezugriff auf vom Check-In-Service hochgeladene Elemente. Nicht für normale Anwendungen vorgesehen."</string> - <string name="permlab_bindGadget">"Gadgets auswählen"</string> - <string name="permdesc_bindGadget">"Bei dieser Option meldet die Anwendung dem System, welche Gadgets von welcher Anwendung verwendet werden können. Mit dieser Genehmigung können Anwendungen anderen Anwendungen Zugriff auf persönliche Daten geben. Nicht für normale Anwendungen vorgesehen."</string> + <!-- no translation found for permlab_bindGadget (776905339015863471) --> + <skip /> + <!-- no translation found for permdesc_bindGadget (2098697834497452046) --> + <skip /> <string name="permlab_modifyPhoneState">"Telefonstatus ändern"</string> <string name="permdesc_modifyPhoneState">"Ermöglicht einer Anwendung, die Telefonfunktionen des Gerätes zu steuern. Eine Anwendung mit dieser Berechtigung kann unter anderem das Netzwerk wechseln oder das Radio des Telefons ein- und ausschalten, ohne Sie darüber zu informieren."</string> <string name="permlab_readPhoneState">"Telefonstatus lesen"</string> @@ -405,7 +417,8 @@ <string name="lockscreen_missing_sim_instructions">"Bitte legen Sie eine SIM-Karte ein."</string> <string name="lockscreen_network_locked_message">"Netzwerk gesperrt"</string> <string name="lockscreen_sim_puk_locked_message">"SIM-Karte ist gesperrt. PUK-Eingabe erforderlich."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Wenden Sie sich an den Kunden-Support."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIM-Karte ist gesperrt."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"SIM-Karte wird entsperrt..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%d</xliff:g>-mal falsch gezeichnet. "\n\n"Versuchen Sie es in <xliff:g id="NUMBER_1">%d</xliff:g> Sekunden erneut."</string> @@ -413,7 +426,8 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Versuchen Sie es in <xliff:g id="NUMBER">%d</xliff:g> Sekunden erneut."</string> <string name="lockscreen_forgot_pattern_button_text">"Muster vergessen?"</string> <string name="lockscreen_glogin_too_many_attempts">"Zu viele Versuche!"</string> - <string name="lockscreen_glogin_instructions">"Melden Sie sich zum Entsperren"\n"mit Ihrem Google-Konto an."</string> + <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) --> + <skip /> <string name="lockscreen_glogin_username_hint">"Nutzername (E-Mail)"</string> <string name="lockscreen_glogin_password_hint">"Passwort"</string> <string name="lockscreen_glogin_submit_button">"Anmelden"</string> @@ -552,6 +566,8 @@ <string name="monthly">"Monatlich"</string> <string name="yearly">"Jährlich"</string> <string name="VideoView_error_title">"Video kann nicht wiedergegeben werden."</string> + <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) --> + <skip /> <string name="VideoView_error_text_unknown">"Dieses Video kann leider nicht abgespielt werden."</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"AM"</string> @@ -573,14 +589,14 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"Mittag"</string> <string name="Noon">"Mittag"</string> <string name="midnight">"Mitternacht"</string> <string name="Midnight">"Mitternacht"</string> <!-- no translation found for month_day (3693060561170538204) --> <skip /> - <!-- no translation found for month (1976700695144952053) --> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for month_year (2106203387378728384) --> @@ -616,7 +632,7 @@ <skip /> <!-- no translation found for abbrev_month_day (3156047263406783231) --> <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"Sonntag"</string> <string name="day_of_week_long_monday">"Montag"</string> @@ -810,6 +826,8 @@ <skip /> <!-- no translation found for ime_action_next (3138843904009813834) --> <skip /> + <!-- no translation found for ime_action_done (8971516117910934605) --> + <skip /> <!-- no translation found for ime_action_default (2840921885558045721) --> <skip /> </resources> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 495f8aa..30061e2 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"El ID de emisor presenta el valor predeterminado de no restringido. Siguiente llamada: No restringido"</string> <string name="serviceNotProvisioned">"El servicio no se suministra."</string> <string name="CLIRPermanent">"El ID del emisor no se puede modificar."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Voz"</string> <string name="serviceClassData">"Datos"</string> <string name="serviceClassFAX">"FAX"</string> @@ -286,8 +296,10 @@ <string name="permdesc_locationUpdates">"Permite habilitar/inhabilitar las notificaciones de actualización de la señal móvil. No está destinado al uso por parte de aplicaciones normales."</string> <string name="permlab_checkinProperties">"acceder a propiedades de registro"</string> <string name="permdesc_checkinProperties">"Permite el acceso de lectura/escritura a las propiedades cargadas por el servicio de registro. No está destinado al uso por parte de aplicaciones normales."</string> - <string name="permlab_bindGadget">"seleccionar gadgets"</string> - <string name="permdesc_bindGadget">"Permite a la aplicación indicar al sistema qué gadgets puede utilizar cada aplicación. Con este permiso, las aplicaciones pueden permitir a otras aplicaciones acceder a datos personales. No está destinado al uso por parte de aplicaciones normales."</string> + <!-- no translation found for permlab_bindGadget (776905339015863471) --> + <skip /> + <!-- no translation found for permdesc_bindGadget (2098697834497452046) --> + <skip /> <string name="permlab_modifyPhoneState">"modificar estado del teléfono"</string> <string name="permdesc_modifyPhoneState">"Permite que la aplicación controle las funciones de teléfono del dispositivo. Una aplicación con este permiso puede cambiar redes, activar y desactivar la señal móvil, etc., sin necesidad de notificar al usuario."</string> <string name="permlab_readPhoneState">"leer el estado del teléfono"</string> @@ -405,7 +417,8 @@ <string name="lockscreen_missing_sim_instructions">"Inserta una tarjeta SIM."</string> <string name="lockscreen_network_locked_message">"Bloqueada para la red"</string> <string name="lockscreen_sim_puk_locked_message">"La tarjeta SIM está bloqueada con el código PUK."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Ponte en contacto con el servicio de atención al cliente."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"La tarjeta SIM está bloqueada."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"Desbloqueando tarjeta SIM..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"Has realizado <xliff:g id="NUMBER_0">%d</xliff:g> intentos fallidos de creación de un patrón de desbloqueo. "\n\n"Inténtalo de nuevo dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string> @@ -413,7 +426,8 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Espera <xliff:g id="NUMBER">%d</xliff:g> segundos y vuelve a intentarlo."</string> <string name="lockscreen_forgot_pattern_button_text">"¿Has olvidado el patrón?"</string> <string name="lockscreen_glogin_too_many_attempts">"Se han realizado demasiados intentos incorrectos de creación del patrón."</string> - <string name="lockscreen_glogin_instructions">"Para desbloquear el teléfono,"\n"accede a tu cuenta de Google"</string> + <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) --> + <skip /> <string name="lockscreen_glogin_username_hint">"Nombre de usuario (correo electrónico)"</string> <string name="lockscreen_glogin_password_hint">"Contraseña"</string> <string name="lockscreen_glogin_submit_button">"Acceder"</string> @@ -552,6 +566,8 @@ <string name="monthly">"Mensualmente"</string> <string name="yearly">"Anualmente"</string> <string name="VideoView_error_title">"No se puede reproducir el vídeo."</string> + <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) --> + <skip /> <string name="VideoView_error_text_unknown">"Este vídeo no se puede reproducir."</string> <string name="VideoView_error_button">"Aceptar"</string> <string name="am">"a.m."</string> @@ -573,14 +589,14 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' de '<xliff:g id="MONTH">MMM</xliff:g>' de '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"mediodía"</string> <string name="Noon">"Mediodía"</string> <string name="midnight">"medianoche"</string> <string name="Midnight">"Medianoche"</string> <!-- no translation found for month_day (3693060561170538204) --> <skip /> - <!-- no translation found for month (1976700695144952053) --> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for month_year (2106203387378728384) --> @@ -616,7 +632,7 @@ <skip /> <!-- no translation found for abbrev_month_day (3156047263406783231) --> <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"Domingo"</string> <string name="day_of_week_long_monday">"Lunes"</string> @@ -810,6 +826,8 @@ <skip /> <!-- no translation found for ime_action_next (3138843904009813834) --> <skip /> + <!-- no translation found for ime_action_done (8971516117910934605) --> + <skip /> <!-- no translation found for ime_action_default (2840921885558045721) --> <skip /> </resources> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 8bd064d..b4b9318 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"Par défaut, les identifiants d\'appelant ne sont pas restreints. Appel suivant : non restreint"</string> <string name="serviceNotProvisioned">"Ce service n\'est pas pris en charge."</string> <string name="CLIRPermanent">"Le paramètre Identifiant d\'appelant ne peut pas être modifié."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Voix"</string> <string name="serviceClassData">"Données"</string> <string name="serviceClassFAX">"Télécopie"</string> @@ -286,8 +296,10 @@ <string name="permdesc_locationUpdates">"Permet l\'activation/la désactivation des notifications de mises à jour de la position géographique provenant de la radio. Les applications normales n\'utilisent pas cette fonctionnalité."</string> <string name="permlab_checkinProperties">"Accès aux propriétés d\'enregistrement"</string> <string name="permdesc_checkinProperties">"Permet un accès en lecture/écriture à des propriétés envoyées par le service d\'inscription. Les applications normales n\'utilisent pas cette fonctionnalité."</string> - <string name="permlab_bindGadget">"choisir les gadgets"</string> - <string name="permdesc_bindGadget">"Permet à l\'application de signaler au système quels gadgets peuvent être utilisés pour quelle application. Cette autorisation permet aux applications de fournir l\'accès à des données personnelles à d\'autres applications. Cette option n\'est pas utilisée par les applications standard."</string> + <!-- no translation found for permlab_bindGadget (776905339015863471) --> + <skip /> + <!-- no translation found for permdesc_bindGadget (2098697834497452046) --> + <skip /> <string name="permlab_modifyPhoneState">"Modification de l\'état du téléphone"</string> <string name="permdesc_modifyPhoneState">"Permet à une application de contrôler les fonctionnalités téléphoniques de l\'appareil. Une application bénéficiant de cette autorisation peut changer de réseau, éteindre et allumer la radio du téléphone, etc., sans vous en avertir."</string> <string name="permlab_readPhoneState">"Lecture de l\'état du téléphone"</string> @@ -403,17 +415,19 @@ <string name="lockscreen_missing_sim_message_short">"Aucune carte SIM n\'a été trouvée."</string> <string name="lockscreen_missing_sim_message">"Aucune carte SIM n\'est insérée dans le téléphone."</string> <string name="lockscreen_missing_sim_instructions">"Insérez une carte SIM."</string> - <string name="lockscreen_network_locked_message">"Réseau bloqué"</string> + <string name="lockscreen_network_locked_message">"Réseau verrouillé"</string> <string name="lockscreen_sim_puk_locked_message">"La carte SIM est verrouillée par code PUK."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Veuillez contacter l\'assistance clientèle."</string> - <string name="lockscreen_sim_locked_message">"La carte SIM est bloquée."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> + <string name="lockscreen_sim_locked_message">"Téléphone verrouillé"</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"Déblocage de la carte SIM..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"Vous avez mal reproduit le motif de déverrouillage <xliff:g id="NUMBER_0">%d</xliff:g> fois. "\n\n"Veuillez réessayer dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes."</string> <string name="lockscreen_failed_attempts_almost_glogin">"Vous avez mal saisi le motif de déverrouillage <xliff:g id="NUMBER_0">%d</xliff:g> fois. Au bout de <xliff:g id="NUMBER_1">%d</xliff:g> tentatives supplémentaires, vous devrez débloquer votre téléphone à l\'aide de votre identifiant Google."\n\n"Merci de réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string> <string name="lockscreen_too_many_failed_attempts_countdown">"Réessayez dans <xliff:g id="NUMBER">%d</xliff:g> secondes."</string> <string name="lockscreen_forgot_pattern_button_text">"Motif oublié ?"</string> <string name="lockscreen_glogin_too_many_attempts">"Trop de tentatives de motif !"</string> - <string name="lockscreen_glogin_instructions">"Pour débloquer votre téléphone,"\n"connectez-vous à l\'aide de votre compte Google"</string> + <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) --> + <skip /> <string name="lockscreen_glogin_username_hint">"Nom d\'utilisateur (e-mail)"</string> <string name="lockscreen_glogin_password_hint">"Mot de passe"</string> <string name="lockscreen_glogin_submit_button">"Se connecter"</string> @@ -551,6 +565,8 @@ <string name="monthly">"Tous les mois"</string> <string name="yearly">"Tous les ans"</string> <string name="VideoView_error_title">"Échec de la lecture de la vidéo"</string> + <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) --> + <skip /> <string name="VideoView_error_text_unknown">"Désolé, impossible de lire cette vidéo."</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"AM"</string> @@ -572,13 +588,13 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"midi"</string> <string name="Noon">"Midi"</string> <string name="midnight">"minuit"</string> <string name="Midnight">"Minuit"</string> <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string> - <!-- no translation found for month (1976700695144952053) --> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for month_year (2106203387378728384) --> @@ -613,7 +629,7 @@ <!-- no translation found for abbrev_month_year (5966980891147982768) --> <skip /> <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>"</string> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"dimanche"</string> <string name="day_of_week_long_monday">"lundi"</string> @@ -806,6 +822,8 @@ <skip /> <!-- no translation found for ime_action_next (3138843904009813834) --> <skip /> + <!-- no translation found for ime_action_done (8971516117910934605) --> + <skip /> <!-- no translation found for ime_action_default (2840921885558045721) --> <skip /> </resources> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index b4cf458..f987ae2 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"ID chiamante generalmente non limitato. Prossima chiamata: non limitato"</string> <string name="serviceNotProvisioned">"Servizio non fornito."</string> <string name="CLIRPermanent">"Impossibile modificare l\'impostazione dell\'ID del chiamante."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Voce"</string> <string name="serviceClassData">"Dati"</string> <string name="serviceClassFAX">"FAX"</string> @@ -286,8 +296,10 @@ <string name="permdesc_locationUpdates">"Consente l\'attivazione/disattivazione delle notifiche di aggiornamento della posizione dal segnale cellulare. Da non usare per normali applicazioni."</string> <string name="permlab_checkinProperties">"accesso a proprietà di archiviazione"</string> <string name="permdesc_checkinProperties">"Consente l\'accesso di lettura/scrittura alle proprietà caricate dal servizio di archiviazione. Da non usare per normali applicazioni."</string> - <string name="permlab_bindGadget">"scegliere gadget"</string> - <string name="permdesc_bindGadget">"Consente all\'applicazione di indicare al sistema quali gadget possono essere utilizzati e da quale applicazione. Con questa autorizzazione, le applicazioni possono consentire ad altre applicazioni di accedere a dati personali. Da non usare per normali applicazioni."</string> + <!-- no translation found for permlab_bindGadget (776905339015863471) --> + <skip /> + <!-- no translation found for permdesc_bindGadget (2098697834497452046) --> + <skip /> <string name="permlab_modifyPhoneState">"modifica stato del telefono"</string> <string name="permdesc_modifyPhoneState">"Consente all\'applicazione di controllare le funzioni telefoniche del dispositivo. Un\'applicazione con questa autorizzazione può cambiare rete, attivare e disattivare il segnale cellulare e così via, senza alcuna notifica."</string> <string name="permlab_readPhoneState">"lettura stato del telefono"</string> @@ -405,7 +417,8 @@ <string name="lockscreen_missing_sim_instructions">"Inserisci una SIM."</string> <string name="lockscreen_network_locked_message">"Rete bloccata"</string> <string name="lockscreen_sim_puk_locked_message">"La SIM è bloccata tramite PUK."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Contatta il servizio clienti."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"La SIM è bloccata."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"Sblocco SIM..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"<xliff:g id="NUMBER_0">%d</xliff:g> tentativi di inserimento della sequenza di sblocco. "\n\n"Riprova fra <xliff:g id="NUMBER_1">%d</xliff:g> secondi."</string> @@ -413,7 +426,8 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Riprova fra <xliff:g id="NUMBER">%d</xliff:g> secondi."</string> <string name="lockscreen_forgot_pattern_button_text">"Hai dimenticato la sequenza?"</string> <string name="lockscreen_glogin_too_many_attempts">"Troppi tentativi di inserimento della sequenza."</string> - <string name="lockscreen_glogin_instructions">"Per sbloccare,"\n"accedi tramite il tuo account Google"</string> + <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) --> + <skip /> <string name="lockscreen_glogin_username_hint">"Nome utente (email)"</string> <string name="lockscreen_glogin_password_hint">"Password"</string> <string name="lockscreen_glogin_submit_button">"Accedi"</string> @@ -552,6 +566,8 @@ <string name="monthly">"Mensilmente"</string> <string name="yearly">"Annualmente"</string> <string name="VideoView_error_title">"Impossibile riprodurre il video"</string> + <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) --> + <skip /> <string name="VideoView_error_text_unknown">"Spiacenti. Impossibile riprodurre il video."</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"AM"</string> @@ -573,14 +589,14 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"mezzogiorno"</string> <string name="Noon">"Mezzogiorno"</string> <string name="midnight">"mezzanotte"</string> <string name="Midnight">"Mezzanotte"</string> <!-- no translation found for month_day (3693060561170538204) --> <skip /> - <!-- no translation found for month (1976700695144952053) --> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for month_year (2106203387378728384) --> @@ -616,7 +632,7 @@ <skip /> <!-- no translation found for abbrev_month_day (3156047263406783231) --> <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"Domenica"</string> <string name="day_of_week_long_monday">"Lunedì"</string> @@ -725,7 +741,7 @@ <string name="anr_activity_process">"L\'attività <xliff:g id="ACTIVITY">%1$s</xliff:g> (nel processo <xliff:g id="PROCESS">%2$s</xliff:g>) non risponde."</string> <string name="anr_application_process">"L\'applicazione <xliff:g id="APPLICATION">%1$s</xliff:g> (nel processo <xliff:g id="PROCESS">%2$s</xliff:g>) non risponde."</string> <string name="anr_process">"Il processo <xliff:g id="PROCESS">%1$s</xliff:g> non risponde."</string> - <string name="force_close">"Forza chiusura"</string> + <string name="force_close">"Termina"</string> <string name="wait">"Attendi"</string> <string name="debug">"Debug"</string> <string name="sendText">"Seleziona un\'azione per il testo"</string> @@ -810,6 +826,8 @@ <skip /> <!-- no translation found for ime_action_next (3138843904009813834) --> <skip /> + <!-- no translation found for ime_action_done (8971516117910934605) --> + <skip /> <!-- no translation found for ime_action_default (2840921885558045721) --> <skip /> </resources> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 2a21bd3..25d906f 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"既定: 発信者番号通知、次の発信: 通知"</string> <string name="serviceNotProvisioned">"提供可能なサービスがありません。"</string> <string name="CLIRPermanent">"発信者番号の設定は変更できません。"</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"音声"</string> <string name="serviceClassData">"データ"</string> <string name="serviceClassFAX">"FAX"</string> @@ -69,7 +79,7 @@ <string name="cfTemplateRegisteredTime">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:転送できません"</string> <string name="httpErrorOk">"OK"</string> <string name="httpError">"ウェブページにエラーがあります。"</string> - <string name="httpErrorLookup">"URLが見つかりませんでした。"</string> + <string name="httpErrorLookup">"URLが見つかりません。"</string> <string name="httpErrorUnsupportedAuthScheme">"このサイトの認証方式には対応していません。"</string> <string name="httpErrorAuth">"認証できませんでした。"</string> <string name="httpErrorProxyAuth">"プロキシサーバーを使用した認証に失敗しました。"</string> @@ -279,15 +289,17 @@ <string name="permlab_hardware_test">"ハードウェアのテスト"</string> <string name="permdesc_hardware_test">"ハードウェアのテストのためにさまざまな周辺機器を制御することをアプリケーションに許可します。"</string> <string name="permlab_callPhone">"電話番号発信"</string> - <string name="permdesc_callPhone">"アプリケーションが電話を自動発信することを許可します。悪意のあるアプリケーションが意図しない電話をかけて料金が発生する恐れがあります。緊急呼への発信は許可しません。"</string> + <string name="permdesc_callPhone">"電話番号の自動発信をアプリケーションに許可します。悪意のあるアプリケーションが意図しない電話をかけて料金が発生する恐れがあります。緊急通報への発信は許可しません。"</string> <string name="permlab_callPrivileged">"電話番号発信"</string> - <string name="permdesc_callPrivileged">"緊急呼を含めあらゆる電話番号に自動発信することをアプリケーションに許可します。悪意のあるアプリケーションが緊急サービスに不正な通報をする恐れがあります。"</string> + <string name="permdesc_callPrivileged">"緊急通報を含めあらゆる電話番号に自動発信することをアプリケーションに許可します。悪意のあるアプリケーションが緊急サービスに不正な通報をする恐れがあります。"</string> <string name="permlab_locationUpdates">"位置情報の更新通知"</string> <string name="permdesc_locationUpdates">"無線通信からの位置更新通知を有効/無効にすることを許可します。通常のアプリケーションでは使用しません。"</string> <string name="permlab_checkinProperties">"チェックインプロパティへのアクセス"</string> <string name="permdesc_checkinProperties">"チェックインサービスがアップロードしたプロパティへの読み書きを許可します。通常のアプリケーションでは使用しません。"</string> - <string name="permlab_bindGadget">"ガジェットの選択"</string> - <string name="permdesc_bindGadget">"特定のアプリケーションで使用可能なガジェットをシステムに指定することをアプリケーションに許可します。この許可を受けたアプリケーションは、他のアプリケーションに個人データへのアクセスを許可することができます。通常のアプリケーションでは使用しません。"</string> + <!-- no translation found for permlab_bindGadget (776905339015863471) --> + <skip /> + <!-- no translation found for permdesc_bindGadget (2098697834497452046) --> + <skip /> <string name="permlab_modifyPhoneState">"端末ステータスの変更"</string> <string name="permdesc_modifyPhoneState">"端末の電話機能のコントロールをアプリケーションに許可します。アプリケーションは、ネットワークの切り替え、携帯電話の無線通信のオン/オフなどを通知せずに行うことができます。"</string> <string name="permlab_readPhoneState">"端末ステータスの読み取り"</string> @@ -316,7 +328,7 @@ <string name="permdesc_writeApnSettings">"APNのプロキシやポートなどのAPN設定の変更をアプリケーションに許可します。"</string> <string name="permlab_changeNetworkState">"ネットワーク接続の変更"</string> <string name="permdesc_changeNetworkState">"ネットワークの接続状態の変更をアプリケーションに許可します。"</string> - <string name="permlab_changeBackgroundDataSetting">"バックグラウンドデータ使用の設定の変更"</string> + <string name="permlab_changeBackgroundDataSetting">"バックグラウンドデータ使用設定の変更"</string> <string name="permdesc_changeBackgroundDataSetting">"バックグラウンドデータ使用の設定の変更をアプリケーションに許可します。"</string> <string name="permlab_accessWifiState">"Wi-Fi状態の表示"</string> <string name="permdesc_accessWifiState">"Wi-Fi状態に関する情報の表示をアプリケーションに許可します。"</string> @@ -388,13 +400,13 @@ <string name="keyguard_password_enter_pin_code">"PINコードを入力"</string> <string name="keyguard_password_wrong_pin_code">"PINコードが正しくありません。"</string> <string name="keyguard_label_text">"ロックを解除するにはMENU、0キーの順に押します。"</string> - <string name="emergency_call_dialog_number_for_display">"緊急呼番号"</string> + <string name="emergency_call_dialog_number_for_display">"緊急通報番号"</string> <string name="lockscreen_carrier_default">"(サービス登録なし)"</string> <string name="lockscreen_screen_locked">"画面ロック中"</string> - <string name="lockscreen_instructions_when_pattern_enabled">"MENUキーでロック解除(または緊急呼)"</string> + <string name="lockscreen_instructions_when_pattern_enabled">"MENUキーでロック解除(または緊急通報)"</string> <string name="lockscreen_instructions_when_pattern_disabled">"MENUキーでロック解除"</string> <string name="lockscreen_pattern_instructions">"ロックを解除するパターンを入力"</string> - <string name="lockscreen_emergency_call">"緊急呼"</string> + <string name="lockscreen_emergency_call">"緊急通報"</string> <string name="lockscreen_pattern_correct">"一致しました"</string> <string name="lockscreen_pattern_wrong">"やり直してください"</string> <!-- no translation found for lockscreen_plugged_in (613343852842944435) --> @@ -405,7 +417,8 @@ <string name="lockscreen_missing_sim_instructions">"SIMカードを挿入してください。"</string> <string name="lockscreen_network_locked_message">"ネットワークがロックされました"</string> <string name="lockscreen_sim_puk_locked_message">"SIMカードはPUKでロックされています。"</string> - <string name="lockscreen_sim_puk_locked_instructions">"お客様サポートにお問い合わせください。"</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIMカードはロックされています。"</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"SIMカードのロック解除中..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"ロック解除のパターンは<xliff:g id="NUMBER_0">%d</xliff:g>回とも正しく指定されていません。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒後にもう一度指定してください。"</string> @@ -413,7 +426,8 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"<xliff:g id="NUMBER">%d</xliff:g>秒後にやり直してください。"</string> <string name="lockscreen_forgot_pattern_button_text">"パターンを忘れた場合"</string> <string name="lockscreen_glogin_too_many_attempts">"パターンのエラーが多すぎます"</string> - <string name="lockscreen_glogin_instructions">"ロックを解除するには、"\n"Googleアカウントでログインしてください。"</string> + <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) --> + <skip /> <string name="lockscreen_glogin_username_hint">"ユーザー名 (メール)"</string> <string name="lockscreen_glogin_password_hint">"パスワード"</string> <string name="lockscreen_glogin_submit_button">"ログイン"</string> @@ -427,7 +441,7 @@ <skip /> <string name="status_bar_clear_all_button">"通知を消去"</string> <string name="status_bar_no_notifications_title">"通知なし"</string> - <string name="status_bar_ongoing_events_title">"継続中"</string> + <string name="status_bar_ongoing_events_title">"操作中"</string> <string name="status_bar_latest_events_title">"通知"</string> <!-- no translation found for battery_status_text_percent_format (7660311274698797147) --> <skip /> @@ -441,7 +455,7 @@ <string name="factorytest_reboot">"再起動"</string> <string name="js_dialog_title">"ページ「<xliff:g id="TITLE">%s</xliff:g>」の記述:"</string> <string name="js_dialog_title_default">"JavaScript"</string> - <string name="js_dialog_before_unload">"このページから移動しますか?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"続行する場合は[OK]、今のページに残る場合は[キャンセル]を選択してください。"</string> + <string name="js_dialog_before_unload">"このページから移動しますか?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"移動する場合は[OK]、今のページに残る場合は[キャンセル]を選択してください。"</string> <string name="save_password_label">"確認"</string> <string name="save_password_message">"このパスワードをブラウザで保存しますか?"</string> <string name="save_password_notnow">"今は保存しない"</string> @@ -498,7 +512,7 @@ </plurals> <plurals name="abbrev_num_minutes_ago"> <item quantity="one">"1分前"</item> - <item quantity="other">"<xliff:g id="COUNT">%d</xliff:g>分後"</item> + <item quantity="other">"<xliff:g id="COUNT">%d</xliff:g>分前"</item> </plurals> <plurals name="abbrev_num_hours_ago"> <item quantity="one">"1時間前"</item> @@ -552,6 +566,8 @@ <string name="monthly">"毎月"</string> <string name="yearly">"毎年"</string> <string name="VideoView_error_title">"動画を再生できません"</string> + <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) --> + <skip /> <string name="VideoView_error_text_unknown">"この動画は再生できません。"</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"AM"</string> @@ -565,22 +581,22 @@ <string name="time_wday_date">"<xliff:g id="DATE">%3$s</xliff:g><xliff:g id="WEEKDAY">%2$s</xliff:g><xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> <string name="wday_date">"<xliff:g id="DATE">%3$s</xliff:g><xliff:g id="WEEKDAY">%2$s</xliff:g>"</string> <string name="time_date">"<xliff:g id="DATE">%3$s</xliff:g>、<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> - <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>、<xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>、<xliff:g id="TIME">%2$s</xliff:g>"</string> + <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>"</string> + <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="time_wday">"<xliff:g id="WEEKDAY">%2$s</xliff:g>、<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string> <string name="full_date_month_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>'/'<xliff:g id="MONTH">MMMM</xliff:g>'/'<xliff:g id="DAY">d</xliff:g>"</string> <string name="full_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>'年'<xliff:g id="MONTH">MMMM</xliff:g>'月'<xliff:g id="DAY">d</xliff:g>'日'"</string> <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>'/'<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>'年'"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'/'<xliff:g id="MONTH">MMM</xliff:g>'/'<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"正午"</string> <string name="Noon">"正午"</string> <string name="midnight">"午前0時"</string> <string name="Midnight">"午前0時"</string> <!-- no translation found for month_day (3693060561170538204) --> <skip /> - <!-- no translation found for month (1976700695144952053) --> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g>年<xliff:g id="MONTH">%B</xliff:g><xliff:g id="DAY">%-d</xliff:g>日"</string> <!-- no translation found for month_year (2106203387378728384) --> @@ -616,7 +632,7 @@ <skip /> <!-- no translation found for abbrev_month_day (3156047263406783231) --> <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"日曜日"</string> <string name="day_of_week_long_monday">"月曜日"</string> @@ -632,20 +648,20 @@ <string name="day_of_week_medium_thursday">"(木)"</string> <string name="day_of_week_medium_friday">"(金)"</string> <string name="day_of_week_medium_saturday">"(土)"</string> - <string name="day_of_week_short_sunday">"(日)"</string> - <string name="day_of_week_short_monday">"(月)"</string> - <string name="day_of_week_short_tuesday">"(火)"</string> - <string name="day_of_week_short_wednesday">"(水)"</string> - <string name="day_of_week_short_thursday">"(木)"</string> - <string name="day_of_week_short_friday">"(金)"</string> - <string name="day_of_week_short_saturday">"(土)"</string> - <string name="day_of_week_shorter_sunday">"(日)"</string> + <string name="day_of_week_short_sunday">"日"</string> + <string name="day_of_week_short_monday">"月"</string> + <string name="day_of_week_short_tuesday">"火"</string> + <string name="day_of_week_short_wednesday">"水"</string> + <string name="day_of_week_short_thursday">"木"</string> + <string name="day_of_week_short_friday">"金"</string> + <string name="day_of_week_short_saturday">"土"</string> + <string name="day_of_week_shorter_sunday">"日"</string> <string name="day_of_week_shorter_monday">"月"</string> - <string name="day_of_week_shorter_tuesday">"(火)"</string> + <string name="day_of_week_shorter_tuesday">"火"</string> <string name="day_of_week_shorter_wednesday">"水"</string> - <string name="day_of_week_shorter_thursday">"(木)"</string> + <string name="day_of_week_shorter_thursday">"木"</string> <string name="day_of_week_shorter_friday">"金"</string> - <string name="day_of_week_shorter_saturday">"(土)"</string> + <string name="day_of_week_shorter_saturday">"土"</string> <string name="day_of_week_shortest_sunday">"日"</string> <string name="day_of_week_shortest_monday">"月"</string> <string name="day_of_week_shortest_tuesday">"火"</string> @@ -712,7 +728,7 @@ <string name="dialog_alert_title">"注意"</string> <string name="capital_on">"オン"</string> <string name="capital_off">"オフ"</string> - <string name="whichApplication">"操作の完了に使用"</string> + <string name="whichApplication">"アプリケーションを選択"</string> <string name="alwaysUse">"常にこの操作で使用する"</string> <string name="clearDefaultHintMsg">"ホームの[設定]>[アプリケーション]>[アプリケーションの管理]でデフォルト設定をクリアします。"</string> <string name="chooseActivity">"操作の選択"</string> @@ -810,6 +826,8 @@ <skip /> <!-- no translation found for ime_action_next (3138843904009813834) --> <skip /> + <!-- no translation found for ime_action_done (8971516117910934605) --> + <skip /> <!-- no translation found for ime_action_default (2840921885558045721) --> <skip /> </resources> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 8fc7d12..faa1267 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"발신자 번호가 기본적으로 제한되지 않음으로 설정됩니다. 다음 통화: 제한되지 않음"</string> <string name="serviceNotProvisioned">"서비스가 준비되지 않았습니다."</string> <string name="CLIRPermanent">"발신자 번호 설정을 변경할 수 없습니다."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"음성"</string> <string name="serviceClassData">"데이터"</string> <string name="serviceClassFAX">"팩스"</string> @@ -286,8 +296,10 @@ <string name="permdesc_locationUpdates">"무선의 위치 업데이트 알림을 활성화하거나 비활성화할 수 있습니다. 일반 응용프로그램에서는 사용하지 않습니다."</string> <string name="permlab_checkinProperties">"체크인 속성 액세스"</string> <string name="permdesc_checkinProperties">"체크인 서비스에서 업로드한 속성에 대한 읽기/쓰기 액세스를 허용합니다. 일반 응용프로그램에서는 사용하지 않습니다."</string> - <string name="permlab_bindGadget">"가젯 선택"</string> - <string name="permdesc_bindGadget">"어느 응용프로그램이 어느 가젯을 사용할 수 있는지 시스템에 알려 주는 권한을 본 응용프로그램에 부여합니다. 이 권한을 사용하면 응용프로그램이 개인 데이터에 대한 액세스 권한을 다른 응용프로그램에 제공할 수 있습니다. 일반 응용프로그램은 이 권한을 사용할 수 없습니다."</string> + <!-- no translation found for permlab_bindGadget (776905339015863471) --> + <skip /> + <!-- no translation found for permdesc_bindGadget (2098697834497452046) --> + <skip /> <string name="permlab_modifyPhoneState">"전화기 상태 수정"</string> <string name="permdesc_modifyPhoneState">"응용프로그램이 장치의 전화 기능을 제어할 수 있습니다. 이 권한을 갖는 응용프로그램은 사용자에게 알리지 않고 네트워크를 전환하거나, 전화 무선 기능을 켜고 끌 수 있습니다."</string> <string name="permlab_readPhoneState">"전화기 상태 읽기"</string> @@ -405,7 +417,8 @@ <string name="lockscreen_missing_sim_instructions">"SIM 카드를 삽입하세요."</string> <string name="lockscreen_network_locked_message">"네트워크 잠김"</string> <string name="lockscreen_sim_puk_locked_message">"SIM 카드의 PUK가 잠겨 있습니다."</string> - <string name="lockscreen_sim_puk_locked_instructions">"고객지원팀에 문의하세요."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIM 카드가 잠겨 있습니다."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"SIM 카드 잠금해제 중..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%d</xliff:g>회 잘못 가져왔습니다. "\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>초 후에 다시 시도하세요."</string> @@ -413,7 +426,8 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"<xliff:g id="NUMBER">%d</xliff:g>초 후에 다시 입력하세요."</string> <string name="lockscreen_forgot_pattern_button_text">"패턴을 잊으셨나요?"</string> <string name="lockscreen_glogin_too_many_attempts">"패턴을 너무 많이 시도했습니다."</string> - <string name="lockscreen_glogin_instructions">"잠금해제하려면"\n"Google 계정으로 로그인하세요."</string> + <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) --> + <skip /> <string name="lockscreen_glogin_username_hint">"사용자 이름(이메일)"</string> <string name="lockscreen_glogin_password_hint">"비밀번호"</string> <string name="lockscreen_glogin_submit_button">"로그인"</string> @@ -552,6 +566,8 @@ <string name="monthly">"매월"</string> <string name="yearly">"매년"</string> <string name="VideoView_error_title">"동영상 재생 안 됨"</string> + <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) --> + <skip /> <string name="VideoView_error_text_unknown">"죄송합니다. 동영상을 재생할 수 없습니다."</string> <string name="VideoView_error_button">"확인"</string> <string name="am">"AM"</string> @@ -573,14 +589,14 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"정오"</string> <string name="Noon">"정오"</string> <string name="midnight">"자정"</string> <string name="Midnight">"자정"</string> <!-- no translation found for month_day (3693060561170538204) --> <skip /> - <!-- no translation found for month (1976700695144952053) --> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g>, <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string> <!-- no translation found for month_year (2106203387378728384) --> @@ -616,7 +632,7 @@ <skip /> <!-- no translation found for abbrev_month_day (3156047263406783231) --> <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"일요일"</string> <string name="day_of_week_long_monday">"월요일"</string> @@ -810,6 +826,8 @@ <skip /> <!-- no translation found for ime_action_next (3138843904009813834) --> <skip /> + <!-- no translation found for ime_action_done (8971516117910934605) --> + <skip /> <!-- no translation found for ime_action_default (2840921885558045721) --> <skip /> </resources> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index c1944a4..61b8928 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"Nummervisning er ikke begrenset som standard. Neste anrop: Ikke begrenset"</string> <string name="serviceNotProvisioned">"SIM-kortet er ikke tilrettelagt for tjenesten."</string> <string name="CLIRPermanent">"Kunne ikke endre innstilling for nummervisning."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Tale"</string> <string name="serviceClassData">"Data"</string> <string name="serviceClassFAX">"Fax"</string> @@ -286,8 +296,10 @@ <string name="permdesc_locationUpdates">"Lar applikasjonen slå av/på varsling om plasseringsendringer fra radioen. Ikke ment for vanlige applikasjoner."</string> <string name="permlab_checkinProperties">"få tilgang til egenskaper for innsjekking"</string> <string name="permdesc_checkinProperties">"Gir lese- og skrivetilgang til egenskaper lastet opp av innsjekkingstjenesten. Ikke ment for vanlige applikasjoner."</string> - <string name="permlab_bindGadget">"velg gadgeter"</string> - <string name="permdesc_bindGadget">"Lar applikasjonen fortelle systemet hvilke gadgeter som kan brukes av hvilke applikasjoner. Med denne rettigheten kan applikasjoner andre applikasjoner tilgang til personlig data. Ikke ment for vanlige applikasjoner."</string> + <!-- no translation found for permlab_bindGadget (776905339015863471) --> + <skip /> + <!-- no translation found for permdesc_bindGadget (2098697834497452046) --> + <skip /> <string name="permlab_modifyPhoneState">"endre telefontilstand"</string> <string name="permdesc_modifyPhoneState">"Lar applikasjonen kontrollere telefonfunksjonaliteten i enheten. En applikasjon med denne rettigheten kan endre nettverk, slå telefonens radio av eller på og lignende uten noensinne å varsle brukeren."</string> <string name="permlab_readPhoneState">"lese telefontilstand"</string> @@ -405,7 +417,8 @@ <string name="lockscreen_missing_sim_instructions">"Sett inn et SIM-kort."</string> <string name="lockscreen_network_locked_message">"Nettverk ikke tillatt"</string> <string name="lockscreen_sim_puk_locked_message">"SIM-kortet er PUK-låst."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Vennligst ring kundeservice."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIM-kortet er låst."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"Låser opp SIM-kort…"</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%d</xliff:g> times. "\n\n"Please try again in <xliff:g id="NUMBER_1">%d</xliff:g> seconds."</string> @@ -413,7 +426,8 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Prøv igjen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string> <string name="lockscreen_forgot_pattern_button_text">"Glemt mønsteret?"</string> <string name="lockscreen_glogin_too_many_attempts">"Too many pattern attempts!"</string> - <string name="lockscreen_glogin_instructions">"To unlock,"\n"sign in with your Google account"</string> + <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) --> + <skip /> <string name="lockscreen_glogin_username_hint">"Username (email)"</string> <string name="lockscreen_glogin_password_hint">"Password"</string> <string name="lockscreen_glogin_submit_button">"Sign in"</string> @@ -552,6 +566,8 @@ <string name="monthly">"En gang i måneden"</string> <string name="yearly">"En gang i året"</string> <string name="VideoView_error_title">"Cannot play video"</string> + <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) --> + <skip /> <string name="VideoView_error_text_unknown">"Sorry, this video cannot be played."</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"AM"</string> @@ -573,14 +589,14 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"middag"</string> <string name="Noon">"Middag"</string> <string name="midnight">"midnatt"</string> <string name="Midnight">"Midnatt"</string> <!-- no translation found for month_day (3693060561170538204) --> <skip /> - <!-- no translation found for month (1976700695144952053) --> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for month_year (2106203387378728384) --> @@ -616,7 +632,7 @@ <skip /> <!-- no translation found for abbrev_month_day (3156047263406783231) --> <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"søndag"</string> <string name="day_of_week_long_monday">"mandag"</string> @@ -810,6 +826,8 @@ <skip /> <!-- no translation found for ime_action_next (3138843904009813834) --> <skip /> + <!-- no translation found for ime_action_done (8971516117910934605) --> + <skip /> <!-- no translation found for ime_action_default (2840921885558045721) --> <skip /> </resources> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 725e369..2a67cd1 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"Beller-id standaard ingesteld op \'onbeperkt\'. Volgende oproep: onbeperkt."</string> <string name="serviceNotProvisioned">"Service niet voorzien."</string> <string name="CLIRPermanent">"De instelling voor beller-id kan niet worden gewijzigd."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Spraak"</string> <string name="serviceClassData">"Gegevens"</string> <string name="serviceClassFAX">"FAX"</string> @@ -286,8 +296,10 @@ <string name="permdesc_locationUpdates">"Hiermee kunnen updatemeldingen voor locaties van de radio worden ingeschakeld/uitgeschakeld. Niet voor gebruik door normale toepassingen."</string> <string name="permlab_checkinProperties">"toegang tot checkin-eigenschappen"</string> <string name="permdesc_checkinProperties">"Hiermee wordt lees-/schrijftoegang gegeven tot eigenschappen die door de checkin-service zijn geüpload. Niet voor gebruik door normale toepassingen."</string> - <string name="permlab_bindGadget">"gadgets kiezen"</string> - <string name="permdesc_bindGadget">"Hiermee kan een toepassing het systeem melden welke gadgets door welke toepassing kunnen worden gebruikt. Met deze toestemming kunnen toepassingen andere toepassingen toegang geven tot persoonlijke gegevens. Niet voor gebruik door normale toepassingen."</string> + <!-- no translation found for permlab_bindGadget (776905339015863471) --> + <skip /> + <!-- no translation found for permdesc_bindGadget (2098697834497452046) --> + <skip /> <string name="permlab_modifyPhoneState">"telefoonstatus wijzigen"</string> <string name="permdesc_modifyPhoneState">"Hiermee kan de toepassing de telefoonfuncties van het apparaat beheren. Een toepassing met deze machtiging kan schakelen tussen netwerken, de radio van de telefoon in- of uitschakelen en dergelijke zonder dat u hiervan op de hoogte wordt gesteld."</string> <string name="permlab_readPhoneState">"telefoonstatus lezen"</string> @@ -405,7 +417,8 @@ <string name="lockscreen_missing_sim_instructions">"Plaats een SIM-kaart."</string> <string name="lockscreen_network_locked_message">"Netwerk geblokkeerd"</string> <string name="lockscreen_sim_puk_locked_message">"SIM-kaart is geblokkeerd met PUK-code."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Neem contact op met de klantenservice."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIM-kaart is geblokkeerd."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"SIM-kaart ontgrendelen..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"U heeft uw deblokkeringspatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer onjuist getekend. "\n\n"Probeer het over <xliff:g id="NUMBER_1">%d</xliff:g> seconden opnieuw."</string> @@ -413,7 +426,8 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Probeer het over <xliff:g id="NUMBER">%d</xliff:g> seconden opnieuw."</string> <string name="lockscreen_forgot_pattern_button_text">"Patroon vergeten?"</string> <string name="lockscreen_glogin_too_many_attempts">"Te veel patroonpogingen!"</string> - <string name="lockscreen_glogin_instructions">"U moet zich aanmelden bij uw Google-account"\n"om te ontgrendelen"</string> + <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) --> + <skip /> <string name="lockscreen_glogin_username_hint">"Gebruikersnaam (e-mail)"</string> <string name="lockscreen_glogin_password_hint">"Wachtwoord"</string> <string name="lockscreen_glogin_submit_button">"Aanmelden"</string> @@ -552,6 +566,8 @@ <string name="monthly">"Maandelijks"</string> <string name="yearly">"Jaarlijks"</string> <string name="VideoView_error_title">"Video kan niet worden afgespeeld"</string> + <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) --> + <skip /> <string name="VideoView_error_text_unknown">"Deze video kan niet worden afgespeeld."</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"am"</string> @@ -573,14 +589,14 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"twaalf uur \'s middags"</string> <string name="Noon">"Twaalf uur \'s middags"</string> <string name="midnight">"middernacht"</string> <string name="Midnight">"Middernacht"</string> <!-- no translation found for month_day (3693060561170538204) --> <skip /> - <!-- no translation found for month (1976700695144952053) --> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for month_year (2106203387378728384) --> @@ -616,7 +632,7 @@ <skip /> <!-- no translation found for abbrev_month_day (3156047263406783231) --> <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"Zondag"</string> <string name="day_of_week_long_monday">"Maandag"</string> @@ -810,6 +826,8 @@ <skip /> <!-- no translation found for ime_action_next (3138843904009813834) --> <skip /> + <!-- no translation found for ime_action_done (8971516117910934605) --> + <skip /> <!-- no translation found for ime_action_default (2840921885558045721) --> <skip /> </resources> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 641d335..8c1f61b 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"Identyfikator dzwoniącego ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: nie zastrzeżony"</string> <string name="serviceNotProvisioned">"Usługa nie jest świadczona."</string> <string name="CLIRPermanent">"Nie można zmienić ustawienia identyfikatora dzwoniącego."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Głos"</string> <string name="serviceClassData">"Dane"</string> <string name="serviceClassFAX">"FAKS"</string> @@ -286,8 +296,10 @@ <string name="permdesc_locationUpdates">"Pozwala włączyć/wyłączyć powiadomienia o aktualizacji położenia przez radio. Nie wykorzystywane przez normalne aplikacje."</string> <string name="permlab_checkinProperties">"dostęp do właściwości usługi rezerwacji"</string> <string name="permdesc_checkinProperties">"Pozwala na dostęp z uprawnieniami do odczytu/zapisu do właściwości przesłanych przez usługę rezerwacji. Nie wykorzystywane przez normalne aplikacje."</string> - <string name="permlab_bindGadget">"wybieranie gadżetów"</string> - <string name="permdesc_bindGadget">"Zezwala aplikacjom na wskazywanie systemowi, które gadżety mogą być używane przez inne aplikacje. Z użyciem tego pozwolenia aplikacje mogą udzielać dostępu do danych osobistych innym aplikacjom. Nie jest ono przeznaczone dla zwykłych aplikacji."</string> + <!-- no translation found for permlab_bindGadget (776905339015863471) --> + <skip /> + <!-- no translation found for permdesc_bindGadget (2098697834497452046) --> + <skip /> <string name="permlab_modifyPhoneState">"zmiana stanu telefonu"</string> <string name="permdesc_modifyPhoneState">"Pozwala aplikacji na kontrolowanie funkcji telefonu w urządzeniu. Aplikacja z tymi uprawnieniami może przełączać sieci, włączać i wyłączać radio itp. bez informowania użytkownika."</string> <string name="permlab_readPhoneState">"czytanie stanu telefonu"</string> @@ -405,7 +417,8 @@ <string name="lockscreen_missing_sim_instructions">"Włóż kartę SIM."</string> <string name="lockscreen_network_locked_message">"Sieć zablokowana"</string> <string name="lockscreen_sim_puk_locked_message">"Karta SIM jest zablokowana kodem PUK."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Skontaktuj się z działem obsługi klienta."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"Karta SIM jest zablokowana."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"Odblokowywanie karty SIM..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"Wzór odblokowania został nieprawidłowo narysowany <xliff:g id="NUMBER_0">%d</xliff:g> razy. "\n\n"Spróbuj ponownie za <xliff:g id="NUMBER_1">%d</xliff:g> sekund."</string> @@ -413,7 +426,8 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Spróbuj ponownie za <xliff:g id="NUMBER">%d</xliff:g> sekund."</string> <string name="lockscreen_forgot_pattern_button_text">"Zapomniałeś wzoru?"</string> <string name="lockscreen_glogin_too_many_attempts">"Zbyt wiele prób narysowania wzoru!"</string> - <string name="lockscreen_glogin_instructions">"Aby odblokować,"\n"zaloguj się na koncie Google"</string> + <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) --> + <skip /> <string name="lockscreen_glogin_username_hint">"Nazwa użytkownika (e-mail)"</string> <string name="lockscreen_glogin_password_hint">"Hasło"</string> <string name="lockscreen_glogin_submit_button">"Zaloguj"</string> @@ -552,6 +566,8 @@ <string name="monthly">"Miesięcznie"</string> <string name="yearly">"Co roku"</string> <string name="VideoView_error_title">"Nie można odtworzyć filmu wideo"</string> + <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) --> + <skip /> <string name="VideoView_error_text_unknown">"Niestety, nie można odtworzyć tego filmu wideo."</string> <string name="VideoView_error_button">"OK"</string> <string name="am">"rano"</string> @@ -573,14 +589,14 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"południe"</string> <string name="Noon">"Południe"</string> <string name="midnight">"północ"</string> <string name="Midnight">"Północ"</string> <!-- no translation found for month_day (3693060561170538204) --> <skip /> - <!-- no translation found for month (1976700695144952053) --> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for month_year (2106203387378728384) --> @@ -616,7 +632,7 @@ <skip /> <!-- no translation found for abbrev_month_day (3156047263406783231) --> <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"niedziela"</string> <string name="day_of_week_long_monday">"poniedziałek"</string> @@ -810,6 +826,8 @@ <skip /> <!-- no translation found for ime_action_next (3138843904009813834) --> <skip /> + <!-- no translation found for ime_action_done (8971516117910934605) --> + <skip /> <!-- no translation found for ime_action_default (2840921885558045721) --> <skip /> </resources> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index ba88667..4a99da5 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"Идентификатор звонящего по умолчанию не ограничен. Следующий вызов: не ограничен"</string> <string name="serviceNotProvisioned">"Услуга не предоставляется."</string> <string name="CLIRPermanent">"Нельзя изменить настройки идентификатора звонящего."</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"Голос"</string> <string name="serviceClassData">"Данные"</string> <string name="serviceClassFAX">"ФАКС"</string> @@ -286,8 +296,10 @@ <string name="permdesc_locationUpdates">"Разрешает включение/отключение уведомлений о местоположении по радиосвязи. Не используется обычными приложениями."</string> <string name="permlab_checkinProperties">"открывать свойства проверки"</string> <string name="permdesc_checkinProperties">"Разрешает доступ на чтение и запись к свойствам, загруженным службой проверки. Не используется обычными приложениями."</string> - <string name="permlab_bindGadget">"выбирать гаджеты"</string> - <string name="permdesc_bindGadget">"Позволяет приложению сообщить системе, какие приложения могут использовать какие гаджеты. Это разрешение позволяет приложениям предоставлять другим приложениям доступ к личной информации. Не предназначено для использования обычными приложениями."</string> + <!-- no translation found for permlab_bindGadget (776905339015863471) --> + <skip /> + <!-- no translation found for permdesc_bindGadget (2098697834497452046) --> + <skip /> <string name="permlab_modifyPhoneState">"изменять состояние телефона"</string> <string name="permdesc_modifyPhoneState">"Позволяет приложению управлять телефонными функциями устройства. Приложение с такими полномочиями может переключать сети, включать и выключать радиосвязь и т.д., не сообщая вам об этом."</string> <string name="permlab_readPhoneState">"считывать состояние телефона"</string> @@ -405,7 +417,8 @@ <string name="lockscreen_missing_sim_instructions">"Вставьте SIM-карту."</string> <string name="lockscreen_network_locked_message">"Заблокирована сетью"</string> <string name="lockscreen_sim_puk_locked_message">"SIM-карта заблокирована PUK-кодом."</string> - <string name="lockscreen_sim_puk_locked_instructions">"Свяжитесь со службой поддержки."</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIM-карта заблокирована."</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"Разблокировка SIM-карты..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"Вы неправильно воспроизвели комбинацию разблокировки <xliff:g id="NUMBER_0">%d</xliff:g> раз. "\n\n"Повторите попытку через <xliff:g id="NUMBER_1">%d</xliff:g> сек."</string> @@ -413,7 +426,8 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"Повторите попытку через <xliff:g id="NUMBER">%d</xliff:g> сек."</string> <string name="lockscreen_forgot_pattern_button_text">"Забыли комбинацию?"</string> <string name="lockscreen_glogin_too_many_attempts">"Слишком много попыток ввести комбинацию!"</string> - <string name="lockscreen_glogin_instructions">"Для разблокировки"\n"войдите с помощью своего аккаунта Google"</string> + <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) --> + <skip /> <string name="lockscreen_glogin_username_hint">"Имя пользователя (адрес электронной почты)"</string> <string name="lockscreen_glogin_password_hint">"Пароль"</string> <string name="lockscreen_glogin_submit_button">"Войти"</string> @@ -552,6 +566,8 @@ <string name="monthly">"Ежемесячно"</string> <string name="yearly">"Ежегодно"</string> <string name="VideoView_error_title">"Не удается воспроизвести видео"</string> + <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) --> + <skip /> <string name="VideoView_error_text_unknown">"К сожалению, это видео нельзя воспроизвести."</string> <string name="VideoView_error_button">"ОК"</string> <string name="am">"AM"</string> @@ -573,14 +589,14 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"полдень"</string> <string name="Noon">"Полдень"</string> <string name="midnight">"полночь"</string> <string name="Midnight">"Полночь"</string> <!-- no translation found for month_day (3693060561170538204) --> <skip /> - <!-- no translation found for month (1976700695144952053) --> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for month_year (2106203387378728384) --> @@ -616,7 +632,7 @@ <skip /> <!-- no translation found for abbrev_month_day (3156047263406783231) --> <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"воскресенье"</string> <string name="day_of_week_long_monday">"понедельник"</string> @@ -810,6 +826,8 @@ <skip /> <!-- no translation found for ime_action_next (3138843904009813834) --> <skip /> + <!-- no translation found for ime_action_done (8971516117910934605) --> + <skip /> <!-- no translation found for ime_action_default (2840921885558045721) --> <skip /> </resources> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 346e254..b31c4f4 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"呼叫者 ID 默认情况下不受限制。下一个呼叫:不受限制"</string> <string name="serviceNotProvisioned">"未提供服务。"</string> <string name="CLIRPermanent">"不能更改呼叫者 ID 设置。"</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"语音"</string> <string name="serviceClassData">"数据"</string> <string name="serviceClassFAX">"传真"</string> @@ -286,8 +296,10 @@ <string name="permdesc_locationUpdates">"允许启用/禁用来自收音机的位置更新通知。普通应用程序不能使用此权限。"</string> <string name="permlab_checkinProperties">"访问检入属性"</string> <string name="permdesc_checkinProperties">"允许对检入服务上传的属性进行读/写访问。普通应用程序不能使用此权限。"</string> - <string name="permlab_bindGadget">"选择小工具"</string> - <string name="permdesc_bindGadget">"允许应用程序告诉系统哪些应用程序可以使用哪些小工具。应用程序可以借此授予其他应用程序访问个人数据的权限。普通应用程序不能使用此权限。"</string> + <!-- no translation found for permlab_bindGadget (776905339015863471) --> + <skip /> + <!-- no translation found for permdesc_bindGadget (2098697834497452046) --> + <skip /> <string name="permlab_modifyPhoneState">"修改手机状态"</string> <string name="permdesc_modifyPhoneState">"允许应用程序控制设备的手机功能。具有此权限的应用程序可能会切换网络,打开和关闭手机收音机以及类似操作,而不会通知您。"</string> <string name="permlab_readPhoneState">"读取手机状态"</string> @@ -405,7 +417,8 @@ <string name="lockscreen_missing_sim_instructions">"请插入 SIM 卡。"</string> <string name="lockscreen_network_locked_message">"网络已锁定"</string> <string name="lockscreen_sim_puk_locked_message">"已对 SIM 卡进行 PUK 码锁定。"</string> - <string name="lockscreen_sim_puk_locked_instructions">"请联系客服部门。"</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIM 卡已被锁定。"</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"正在解锁 SIM 卡..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"您 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地绘制了您的解锁图案。"\n\n"请在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒后重试。"</string> @@ -413,7 +426,8 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"<xliff:g id="NUMBER">%d</xliff:g> 秒后重试。"</string> <string name="lockscreen_forgot_pattern_button_text">"忘记了图案?"</string> <string name="lockscreen_glogin_too_many_attempts">"图案尝试次数太多!"</string> - <string name="lockscreen_glogin_instructions">"要解锁,"\n"请用您的 Google 帐户登录"</string> + <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) --> + <skip /> <string name="lockscreen_glogin_username_hint">"用户名(电子邮件)"</string> <string name="lockscreen_glogin_password_hint">"密码"</string> <string name="lockscreen_glogin_submit_button">"登录"</string> @@ -552,6 +566,8 @@ <string name="monthly">"每月"</string> <string name="yearly">"每年"</string> <string name="VideoView_error_title">"无法播放视频"</string> + <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) --> + <skip /> <string name="VideoView_error_text_unknown">"很抱歉,此视频不能播放。"</string> <string name="VideoView_error_button">"确定"</string> <string name="am">"上午"</string> @@ -573,14 +589,14 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="MONTH">MMM</xliff:g>' 月 '<xliff:g id="DAY">d</xliff:g>' 日'"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="DAY">d</xliff:g>' 月 '<xliff:g id="MONTH">MMM</xliff:g>' 日'"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"中午"</string> <string name="Noon">"中午"</string> <string name="midnight">"午夜"</string> <string name="Midnight">"午夜"</string> <!-- no translation found for month_day (3693060561170538204) --> <skip /> - <!-- no translation found for month (1976700695144952053) --> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%B</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> 日"</string> <!-- no translation found for month_year (2106203387378728384) --> @@ -616,7 +632,7 @@ <skip /> <!-- no translation found for abbrev_month_day (3156047263406783231) --> <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"周日"</string> <string name="day_of_week_long_monday">"周一"</string> @@ -810,6 +826,8 @@ <skip /> <!-- no translation found for ime_action_next (3138843904009813834) --> <skip /> + <!-- no translation found for ime_action_done (8971516117910934605) --> + <skip /> <!-- no translation found for ime_action_default (2840921885558045721) --> <skip /> </resources> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 6d4b821..d88ca65 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -54,6 +54,16 @@ <string name="CLIRDefaultOffNextCallOff">"預設顯示本機號碼,下一通也顯示。"</string> <string name="serviceNotProvisioned">"服務未設定完成。"</string> <string name="CLIRPermanent">"本機號碼設定無法變更。"</string> + <!-- no translation found for RestrictedChangedTitle (5592189398956187498) --> + <skip /> + <!-- no translation found for RestrictedOnData (8653794784690065540) --> + <skip /> + <!-- no translation found for RestrictedOnEmergency (6581163779072833665) --> + <skip /> + <!-- no translation found for RestrictedOnNormal (2045364908281990708) --> + <skip /> + <!-- no translation found for RestrictedOnAll (4923139582141626159) --> + <skip /> <string name="serviceClassVoice">"語音"</string> <string name="serviceClassData">"資料"</string> <string name="serviceClassFAX">"傳真"</string> @@ -286,8 +296,10 @@ <string name="permdesc_locationUpdates">"允許啟用/停用無線通訊位置更新通知。一般應用程式不會使用此功能。"</string> <string name="permlab_checkinProperties">"存取登機選項"</string> <string name="permdesc_checkinProperties">"允許讀寫登機服務上傳的資料。一般應用程式不會使用此功能。"</string> - <string name="permlab_bindGadget">"選擇小工具"</string> - <string name="permdesc_bindGadget">"允許應用程式告知系統哪些應用程式可以使用哪些小工具。擁有此權限的應用程式可以讓其他應用程式使用個人資料。一般應用程式不會使用此功能。"</string> + <!-- no translation found for permlab_bindGadget (776905339015863471) --> + <skip /> + <!-- no translation found for permdesc_bindGadget (2098697834497452046) --> + <skip /> <string name="permlab_modifyPhoneState">"修改手機狀態"</string> <string name="permdesc_modifyPhoneState">"允許應用程式控制電話功能。擁有此權限的程式可自行切換網路、開關無線通訊功能。"</string> <string name="permlab_readPhoneState">"讀取手機狀態"</string> @@ -405,7 +417,8 @@ <string name="lockscreen_missing_sim_instructions">"請插入 SIM 卡。"</string> <string name="lockscreen_network_locked_message">"網路已鎖定"</string> <string name="lockscreen_sim_puk_locked_message">"SIM 的 PUK 已鎖定。"</string> - <string name="lockscreen_sim_puk_locked_instructions">"請聯絡客服中心。"</string> + <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) --> + <skip /> <string name="lockscreen_sim_locked_message">"SIM 卡已鎖定。"</string> <string name="lockscreen_sim_unlock_progress_dialog_message">"解鎖 SIM 卡中..."</string> <string name="lockscreen_too_many_failed_attempts_dialog_message">"畫出解鎖圖形已錯誤 <xliff:g id="NUMBER_0">%d</xliff:g> 次。"\n\n" 請在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒後再嘗試。"</string> @@ -413,7 +426,8 @@ <string name="lockscreen_too_many_failed_attempts_countdown">"<xliff:g id="NUMBER">%d</xliff:g> 秒後再試一次。"</string> <string name="lockscreen_forgot_pattern_button_text">"忘記解鎖圖形?"</string> <string name="lockscreen_glogin_too_many_attempts">"解鎖圖形出錯次數過多!"</string> - <string name="lockscreen_glogin_instructions">"若要解鎖,"\n"請以您的 Google 帳戶登入"</string> + <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) --> + <skip /> <string name="lockscreen_glogin_username_hint">"使用者名稱 (電子郵件)"</string> <string name="lockscreen_glogin_password_hint">"密碼"</string> <string name="lockscreen_glogin_submit_button">"登入"</string> @@ -552,6 +566,8 @@ <string name="monthly">"每月"</string> <string name="yearly">"每年"</string> <string name="VideoView_error_title">"無法播放影片"</string> + <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) --> + <skip /> <string name="VideoView_error_text_unknown">"抱歉,無法撥放此影片。"</string> <string name="VideoView_error_button">"確定"</string> <string name="am">"上午"</string> @@ -573,14 +589,14 @@ <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>','<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>','<xliff:g id="YEAR">yyyy</xliff:g>"</string> <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string> - <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> + <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string> <string name="noon">"中午"</string> <string name="Noon">"中午"</string> <string name="midnight">"午夜"</string> <string name="Midnight">"午夜"</string> <!-- no translation found for month_day (3693060561170538204) --> <skip /> - <!-- no translation found for month (1976700695144952053) --> + <!-- no translation found for month (7026169712234774086) --> <skip /> <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>,<xliff:g id="YEAR">%Y</xliff:g>"</string> <!-- no translation found for month_year (2106203387378728384) --> @@ -616,7 +632,7 @@ <skip /> <!-- no translation found for abbrev_month_day (3156047263406783231) --> <skip /> - <!-- no translation found for abbrev_month (7304935052615731208) --> + <!-- no translation found for abbrev_month (3131032032850777433) --> <skip /> <string name="day_of_week_long_sunday">"星期日"</string> <string name="day_of_week_long_monday">"星期一"</string> @@ -810,6 +826,8 @@ <skip /> <!-- no translation found for ime_action_next (3138843904009813834) --> <skip /> + <!-- no translation found for ime_action_done (8971516117910934605) --> + <skip /> <!-- no translation found for ime_action_default (2840921885558045721) --> <skip /> </resources> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 899d109..485edca 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -620,12 +620,35 @@ Corresponds to {@link android.view.inputmethod.EditorInfo#IME_ACTION_DONE}. --> <flag name="actionDone" value="0x00000006" /> + <!-- 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. + <p>Corresponds to + {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_EXTRACT_UI}. --> + <flag name="flagNoExtractUi" value="0x10000000" /> + <!-- Used in conjunction with a custom 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. + <p>Corresponds to + {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_ACCESSORY_ACTION}. --> + <flag name="flagNoAccessoryAction" value="0x20000000" /> <!-- Used in conjunction with a custom action, - this indicates that the action should not - be available in-line as the same as a "enter" key. Typically this is + this 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. + a message. Note that {@link android.widget.TextView} will + automatically set this flag for you on multi-line text views. <p>Corresponds to {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_ENTER_ACTION}. --> <flag name="flagNoEnterAction" value="0x40000000" /> @@ -1372,7 +1395,8 @@ </declare-styleable> <declare-styleable name="FrameLayout"> <!-- Defines the drawable to draw over the content. This can be used as an overlay. - The foreground drawable participates in the padding of the content. --> + The foreground drawable participates in the padding of the content if the gravity + is set to fill. --> <attr name="foreground" format="reference|color" /> <!-- Defines the gravity to apply to the foreground drawable. The gravity defaults to fill. --> @@ -1408,6 +1432,9 @@ edge, a right gravity will clip the left edge, and neither will clip both edges. --> <flag name="clip_horizontal" value="0x08" /> </attr> + <!-- Defines whether the foreground drawable should be drawn inside the padding. + This property is turned on by default. --> + <attr name="foregroundInsidePadding" format="boolean" /> <!-- Determines whether to measure all children or just those in the VISIBLE or INVISIBLE state when measuring. Defaults to false. --> <attr name="measureAllChildren" format="boolean" /> @@ -3024,6 +3051,22 @@ </attr> </declare-styleable> + <declare-styleable name="InputMethodService"> + <!-- Background to use for entire input method when it is being + shown in fullscreen mode with the extract view, to ensure + that it completely covers the application. This allows, + for example, the candidate view to be hidden + while in fullscreen mode without having the application show through + behind it.--> + <attr name="imeFullscreenBackground" format="reference|color" /> + <!-- Animation to use when showing the fullscreen extract UI after + it had previously been hidden. --> + <attr name="imeExtractEnterAnimation" format="reference" /> + <!-- Animation to use when hiding the fullscreen extract UI after + it had previously been shown. --> + <attr name="imeExtractExitAnimation" format="reference" /> + </declare-styleable> + <declare-styleable name="KeyboardView"> <!-- Default KeyboardView style. --> <attr name="keyboardViewStyle" format="reference" /> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 88c7b35..c06c7c4 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1010,6 +1010,9 @@ <public type="attr" name="imeOptions" id="0x01010264" /> <public type="attr" name="imeActionLabel" id="0x01010265" /> <public type="attr" name="imeActionId" id="0x01010266" /> + <public type="attr" name="imeFullscreenBackground" id="0x01010267" /> + <public type="attr" name="imeExtractEnterAnimation" id="0x01010268" /> + <public type="attr" name="imeExtractExitAnimation" id="0x01010269" /> <!-- The part of the UI shown by an {@link android.inputmethodservice.InputMethodService} that contains the diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 761cedd..7aaee1a 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -113,6 +113,17 @@ <!-- Displayed to tell the user that they cannot change the caller ID setting. --> <string name="CLIRPermanent">The caller ID setting cannot be changed.</string> + <!-- Notification title to tell the user that restricted state is changed by access control. --> + <string name="RestrictedChangedTitle">Restricted access changed</string> + <!-- Displayed to tell the user that data service is blocked by access control. --> + <string name="RestrictedOnData">Data service is blocked.</string> + <!-- Displayed to tell the user that emergency service is blocked by access control. --> + <string name="RestrictedOnEmergency">Emergency service is blocked.</string> + <!-- Displayed to tell the user that normal service is blocked by access control. --> + <string name="RestrictedOnNormal">Voice/SMS service is blocked.</string> + <!-- Displayed to tell the user that all voice service is blocked by access control. --> + <string name="RestrictedOnAll">All voice/SMS services are blocked.</string> + <!-- Mappings between TS 27.007 +CFCC/+CLCK "service classes" and human-readable strings--> <skip /> <!-- Example: Service was enabled for: Voice, Data --> <string name="serviceClassVoice">Voice</string> @@ -1148,7 +1159,7 @@ PUK locked (Pin Unlock Kode) --> <string name="lockscreen_sim_puk_locked_message">SIM card is PUK-locked.</string> <!-- Shown in the lock screen when the SIM has become PUK locked and the user must call customer care to unlock it. --> - <string name="lockscreen_sim_puk_locked_instructions">Please contact Customer Care.</string> + <string name="lockscreen_sim_puk_locked_instructions">Please see the User Guide or contact Customer Care.</string> <!-- Shown in the lock screen to tell the user that their SIM is locked and they must unlock it. --> <string name="lockscreen_sim_locked_message">SIM card is locked.</string> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index a152410..fb357a2 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -154,12 +154,11 @@ <!-- Status Bar Styles --> <style name="TextAppearance.StatusBarTitle"> - <item name="android:textSize">14sp</item> + <item name="android:textAppearance">?android:attr/textAppearanceSmall</item> <item name="android:textStyle">bold</item> - <item name="android:textColor">#ffffffff</item> + <item name="android:textColor">?android:attr/textColorPrimary</item> </style> - <!-- Widget Styles --> <style name="Widget"> @@ -317,6 +316,10 @@ <item name="android:paddingLeft">5sp</item> </style> + <style name="Widget.TextView.ListSeparator.White"> + <item name="android:textColor">?textColorSecondaryInverse</item> + </style> + <style name="Widget.EditText"> <item name="android:focusable">true</item> <item name="android:focusableInTouchMode">true</item> @@ -663,7 +666,6 @@ </style> <style name="ZoomControls"> - <item name="android:background">@android:drawable/zoom_plate</item> <item name="android:gravity">bottom</item> <item name="android:paddingLeft">15dip</item> <item name="android:paddingRight">15dip</item> diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index 01c46de..76824c3 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -185,6 +185,7 @@ fills the entire screen --> <style name="Theme.NoTitleBar.Fullscreen"> <item name="android:windowFullscreen">true</item> + <item name="android:windowContentOverlay">@null</item> </style> <!-- Theme for a light background with dark text on top. Set your activity @@ -218,6 +219,7 @@ <item name="listViewStyle">@android:style/Widget.ListView.White</item> <item name="listDivider">@drawable/divider_horizontal_bright</item> + <item name="listSeparatorTextViewStyle">@android:style/Widget.TextView.ListSeparator.White</item> </style> <!-- Variant of the light theme with no title bar --> @@ -229,6 +231,7 @@ fills the entire screen --> <style name="Theme.Light.NoTitleBar.Fullscreen"> <item name="android:windowFullscreen">true</item> + <item name="android:windowContentOverlay">@null</item> </style> <!-- Special variation on the default theme that ensures the background is @@ -249,6 +252,7 @@ fills the entire screen --> <style name="Theme.Black.NoTitleBar.Fullscreen"> <item name="android:windowFullscreen">true</item> + <item name="android:windowContentOverlay">@null</item> </style> <!-- Default theme for translucent activities, that is windows that allow you @@ -269,12 +273,14 @@ fills the entire screen --> <style name="Theme.Translucent.NoTitleBar.Fullscreen"> <item name="android:windowFullscreen">true</item> + <item name="android:windowContentOverlay">@null</item> </style> <!-- Default theme for activities that don't actually display a UI; that is, they finish themselves before being resumed. --> <style name="Theme.NoDisplay"> <item name="android:windowBackground">@null</item> + <item name="android:windowContentOverlay">@null</item> <item name="android:windowIsTranslucent">false</item> <item name="android:windowAnimationStyle">@null</item> <item name="android:windowDisablePreview">true</item> @@ -291,7 +297,7 @@ <item name="android:windowTitleStyle">@android:style/DialogWindowTitle</item> <item name="android:windowBackground">@android:drawable/panel_background</item> <item name="android:windowIsFloating">true</item> - <item name="android:windowContentOverlay">@android:drawable/panel_separator</item> + <item name="android:windowContentOverlay">@null</item> <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item> <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item> </style> @@ -303,21 +309,26 @@ <item name="windowBackground">@android:color/transparent</item> <item name="windowTitleStyle">@android:style/DialogWindowTitle</item> <item name="windowIsFloating">true</item> - <item name="windowContentOverlay">@drawable/panel_separator</item> + <item name="windowContentOverlay">@null</item> </style> - <!-- Default theme for dialog windows and activities, which is used by the - {@link android.app.Dialog} class. This changes the window to be - floating (not fill the entire screen), and puts a frame around its - contents. You can set this theme on an activity if you would like to - make an activity that looks like a Dialog. --> - <style name="Theme.InputMethod" parent="Theme.Light.NoTitleBar"> + <!-- Default theme for input methods, which is used by the + {@link android.inputmethodservice.InputMethodService} class. + this inherits from Theme.NoTitleBar, but makes the background + transparent, the window floating and translucent, and ensures that + it does not dim the UI behind it. This also configures the window + with the standard IME animations and visuals. --> + <style name="Theme.InputMethod" parent="Theme.NoTitleBar"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowFrame">@null</item> + <item name="android:windowContentOverlay">@null</item> <item name="android:windowIsFloating">true</item> <item name="android:backgroundDimEnabled">false</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowAnimationStyle">@android:style/Animation.InputMethod</item> + <item name="android:imeFullscreenBackground">@android:drawable/input_method_fullscreen_background</item> + <item name="android:imeExtractEnterAnimation">@android:anim/input_method_extract_enter</item> + <item name="android:imeExtractExitAnimation">@android:anim/input_method_extract_exit</item> </style> <!-- Theme for the search input bar. --> @@ -358,7 +369,7 @@ <item name="windowTitleStyle">@android:style/DialogWindowTitle</item> <item name="windowBackground">@android:color/transparent</item> <item name="windowIsFloating">true</item> - <item name="windowContentOverlay">@drawable/panel_separator</item> + <item name="windowContentOverlay">@null</item> <item name="textAppearance">@style/TextAppearance.Theme.Dialog.AppError</item> </style> </resources> |