Merge "DO NOT MERGE Check item type before re-binding transient state views" into klp-dev
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index c63e586..cce6fc4 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1778,7 +1778,7 @@
RemoteViews button = new RemoteViews(mContext.getPackageName(),
tombstone ? R.layout.notification_action_tombstone
: R.layout.notification_action);
- button.setTextViewCompoundDrawables(R.id.action0, action.icon, 0, 0, 0);
+ button.setTextViewCompoundDrawablesRelative(R.id.action0, action.icon, 0, 0, 0);
button.setTextViewText(R.id.action0, action.title);
if (!tombstone) {
button.setOnClickPendingIntent(R.id.action0, action.actionIntent);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index e2bc80a..d1f1f2a 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -27,14 +27,14 @@
import android.os.ServiceManager;
import android.util.Log;
import android.util.Pair;
+
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashSet;
import java.util.HashMap;
-import java.util.LinkedList;
+import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
@@ -183,6 +183,43 @@
"android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
/**
+ * Activity Action: Show a system activity to request BLE advertising.<br>
+ * If the device is not doing BLE advertising, this activity will start BLE advertising for the
+ * device, otherwise it will continue BLE advertising using the current
+ * {@link BluetoothAdvScanData}. <br>
+ * Note this activity will also request the user to turn on Bluetooth if it's not currently
+ * enabled.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_START_ADVERTISING =
+ "android.bluetooth.adapter.action.START_ADVERTISING";
+
+ /**
+ * Activity Action: Stop the current BLE advertising.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_STOP_ADVERTISING =
+ "android.bluetooth.adapter.action.STOP_ADVERTISING";
+
+ /**
+ * Broadcast Action: Indicate BLE Advertising is started.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_BLUETOOTH_ADVERTISING_STARTED =
+ "android.bluetooth.adapter.action.ADVERTISING_STARTED";
+
+ /**
+ * Broadcast Action: Indicated BLE Advertising is stopped.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_BLUETOOTH_ADVERTISING_STOPPED =
+ "android.bluetooth.adapter.action.ADVERTISING_STOPPED";
+
+ /**
* Activity Action: Show a system activity that allows the user to turn on
* Bluetooth.
* <p>This system activity will return once Bluetooth has completed turning
@@ -251,7 +288,6 @@
*/
public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
-
/**
* Broadcast Action: The local Bluetooth adapter has started the remote
* device discovery process.
@@ -365,6 +401,8 @@
private IBluetooth mService;
private final Map<LeScanCallback, GattCallbackWrapper> mLeScanClients;
+ private BluetoothAdvScanData mBluetoothAdvScanData = null;
+ private GattCallbackWrapper mAdvertisingCallback;
/**
* Get a handle to the default local Bluetooth adapter.
@@ -438,6 +476,97 @@
}
/**
+ * Returns a {@link BluetoothAdvScanData} object representing advertising data.
+ * @hide
+ */
+ public BluetoothAdvScanData getAdvScanData() {
+ try {
+ IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
+ if (iGatt == null) {
+ // BLE is not supported
+ Log.e(TAG, "failed to start, iGatt null");
+ return null;
+ }
+ if (mBluetoothAdvScanData == null) {
+ mBluetoothAdvScanData = new BluetoothAdvScanData(iGatt, BluetoothAdvScanData.AD);
+ }
+ return mBluetoothAdvScanData;
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to get advScanData, error: " + e);
+ return null;
+ }
+ }
+
+
+ /**
+ * Start BLE advertising using current {@link BluetoothAdvScanData}.
+ * An app should start advertising by requesting
+ * {@link BluetoothAdapter#ACTION_START_ADVERTISING} instead of calling this method directly.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}
+ *
+ * @return true if BLE avertising succeeds, false otherwise.
+ * @hide
+ */
+ public boolean startAdvertising() {
+ if (getState() != STATE_ON) return false;
+
+ try {
+ IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
+ if (iGatt == null) {
+ // BLE is not supported.
+ return false;
+ }
+ // Restart/reset advertising packets if advertising is in progress.
+ if (isAdvertising()) {
+ // Invalid advertising callback.
+ if (mAdvertisingCallback == null || mAdvertisingCallback.mLeHandle == -1) {
+ Log.e(TAG, "failed to restart advertising, invalid callback");
+ return false;
+ }
+ iGatt.startAdvertising(mAdvertisingCallback.mLeHandle);
+ return true;
+ }
+ UUID uuid = UUID.randomUUID();
+ GattCallbackWrapper wrapper =
+ new GattCallbackWrapper(this, null, null, GattCallbackWrapper.CALLBACK_TYPE_ADV);
+ iGatt.registerClient(new ParcelUuid(uuid), wrapper);
+ mAdvertisingCallback = wrapper;
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ return false;
+ }
+ }
+
+ /**
+ * Stop BLE advertising.
+ * An app should stop advertising by requesting
+ * {@link BluetoothAdapter#ACTION_STOP_ADVERTISING} instead of calling this method directly.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}
+ * @return true if BLE advertising stops, false otherwise.
+ * @hide
+ */
+ public boolean stopAdvertisting() {
+ try {
+ IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
+ if (iGatt == null) {
+ // BLE is not supported
+ return false;
+ }
+ if (mAdvertisingCallback == null) {
+ // no callback.
+ return false;
+ }
+ mAdvertisingCallback.stopAdvertising();
+ mAdvertisingCallback = null;
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ return false;
+ }
+ }
+
+ /**
* Return true if Bluetooth is currently enabled and ready for use.
* <p>Equivalent to:
* <code>getBluetoothState() == STATE_ON</code>
@@ -849,6 +978,23 @@
}
/**
+ * Returns whether BLE is currently advertising.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
+ *
+ * @hide
+ */
+ public boolean isAdvertising() {
+ if (getState() != STATE_ON) return false;
+ try {
+ IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
+ return iGatt.isAdvertising();
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ }
+ return false;
+ }
+
+ /**
* Return the set of {@link BluetoothDevice} objects that are bonded
* (paired) to the local adapter.
* <p>If Bluetooth state is not {@link #STATE_ON}, this API
@@ -1546,8 +1692,12 @@
private static class GattCallbackWrapper extends IBluetoothGattCallback.Stub {
private static final int LE_CALLBACK_REG_TIMEOUT = 2000;
private static final int LE_CALLBACK_REG_WAIT_COUNT = 5;
+ private static final int CALLBACK_TYPE_SCAN = 0;
+ private static final int CALLBACK_TYPE_ADV = 1;
private final LeScanCallback mLeScanCb;
+ private int mCallbackType;
+
// mLeHandle 0: not registered
// -1: scan stopped
// >0: registered and scan started
@@ -1561,6 +1711,16 @@
mLeScanCb = leScanCb;
mScanFilter = uuid;
mLeHandle = 0;
+ mCallbackType = CALLBACK_TYPE_SCAN;
+ }
+
+ public GattCallbackWrapper(BluetoothAdapter bluetoothAdapter, LeScanCallback leScanCb,
+ UUID[] uuid, int type) {
+ mBluetoothAdapter = new WeakReference<BluetoothAdapter>(bluetoothAdapter);
+ mLeScanCb = leScanCb;
+ mScanFilter = uuid;
+ mLeHandle = 0;
+ mCallbackType = type;
}
public boolean scanStarted() {
@@ -1583,6 +1743,30 @@
return started;
}
+ public void stopAdvertising() {
+ synchronized (this) {
+ if (mLeHandle <= 0) {
+ Log.e(TAG, "Error state, mLeHandle: " + mLeHandle);
+ return;
+ }
+ BluetoothAdapter adapter = mBluetoothAdapter.get();
+ if (adapter != null) {
+ try {
+ IBluetoothGatt iGatt = adapter.getBluetoothManager().getBluetoothGatt();
+ iGatt.stopAdvertising();
+ Log.d(TAG, "unregeistering client " + mLeHandle);
+ iGatt.unregisterClient(mLeHandle);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to stop advertising and unregister" + e);
+ }
+ } else {
+ Log.e(TAG, "stopAdvertising, BluetoothAdapter is null");
+ }
+ mLeHandle = -1;
+ notifyAll();
+ }
+ }
+
public void stopLeScan() {
synchronized(this) {
if (mLeHandle <= 0) {
@@ -1624,14 +1808,18 @@
BluetoothAdapter adapter = mBluetoothAdapter.get();
if (adapter != null) {
iGatt = adapter.getBluetoothManager().getBluetoothGatt();
- if (mScanFilter == null) {
- iGatt.startScan(mLeHandle, false);
+ if (mCallbackType == CALLBACK_TYPE_ADV) {
+ iGatt.startAdvertising(mLeHandle);
} else {
- ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length];
- for(int i = 0; i != uuids.length; ++i) {
- uuids[i] = new ParcelUuid(mScanFilter[i]);
- }
- iGatt.startScanWithUuids(mLeHandle, false, uuids);
+ if (mScanFilter == null) {
+ iGatt.startScan(mLeHandle, false);
+ } else {
+ ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length];
+ for(int i = 0; i != uuids.length; ++i) {
+ uuids[i] = new ParcelUuid(mScanFilter[i]);
+ }
+ iGatt.startScanWithUuids(mLeHandle, false, uuids);
+ }
}
} else {
Log.e(TAG, "onClientRegistered, BluetoothAdapter null");
@@ -1642,7 +1830,7 @@
mLeHandle = -1;
}
if (mLeHandle == -1) {
- // registration succeeded but start scan failed
+ // registration succeeded but start scan or advertise failed
if (iGatt != null) {
try {
iGatt.unregisterClient(mLeHandle);
diff --git a/core/java/android/bluetooth/BluetoothAdvScanData.java b/core/java/android/bluetooth/BluetoothAdvScanData.java
new file mode 100644
index 0000000..a97b0a8
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothAdvScanData.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+import android.os.ParcelUuid;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.Collections;
+import java.util.List;
+
+
+/**
+ * This class provides the public APIs to set advertising and scan response data when BLE device
+ * operates in peripheral mode. <br>
+ * The exact format is defined in Bluetooth 4.0 specification, Volume 3, Part C, Section 11
+ * @hide
+ */
+public final class BluetoothAdvScanData {
+
+ /**
+ * Available data types of {@link BluetoothAdvScanData}.
+ */
+ public static final int AD = 0; // Advertising Data
+ public static final int SCAN_RESPONSE = 1; // Scan Response
+ public static final int EIR = 2; // Extended Inquiry Response
+
+ private static final String TAG = "BluetoothAdvScanData";
+
+ /**
+ * Data type of BluetoothAdvScanData.
+ */
+ private final int mDataType;
+ /**
+ * Bluetooth Gatt Service.
+ */
+ private IBluetoothGatt mBluetoothGatt;
+
+ /**
+ * @param mBluetoothGatt
+ * @param dataType
+ */
+ public BluetoothAdvScanData(IBluetoothGatt mBluetoothGatt, int dataType) {
+ this.mBluetoothGatt = mBluetoothGatt;
+ this.mDataType = dataType;
+ }
+
+ /**
+ * @return advertising data type.
+ */
+ public int getDataType() {
+ return mDataType;
+ }
+
+ /**
+ * Set manufactureCode and manufactureData.
+ * Returns true if manufacturer data is set, false if there is no enough room to set
+ * manufacturer data or the data is already set.
+ * @param manufacturerCode - unique identifier for the manufacturer
+ * @param manufacturerData - data associated with the specific manufacturer.
+ */
+ public boolean setManufacturerData(int manufacturerCode, byte[] manufacturerData) {
+ if (mDataType != AD) return false;
+ try {
+ return mBluetoothGatt.setAdvManufacturerCodeAndData(manufacturerCode, manufacturerData);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Set service data. Note the service data can only be set when the data type is {@code AD};
+ * @param serviceData
+ */
+ public boolean setServiceData(byte[] serviceData) {
+
+ if (mDataType != AD) return false;
+ if (serviceData == null) return false;
+ try {
+ return mBluetoothGatt.setAdvServiceData(serviceData);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns an immutable list of service uuids that will be advertised.
+ */
+ public List<ParcelUuid> getServiceUuids() {
+ try {
+ return Collections.unmodifiableList(mBluetoothGatt.getAdvServiceUuids());
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns manufacturer data.
+ */
+ public byte[] getManufacturerData() {
+ if (mBluetoothGatt == null) return null;
+ try {
+ return mBluetoothGatt.getAdvManufacturerData();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns service data.
+ */
+ public byte[] getServiceData() {
+ if (mBluetoothGatt == null) return null;
+ try {
+ return mBluetoothGatt.getAdvServiceData();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Remove manufacturer data based on given manufacturer code.
+ * @param manufacturerCode
+ */
+ public void removeManufacturerCodeAndData(int manufacturerCode) {
+ if (mBluetoothGatt != null) {
+ try {
+ mBluetoothGatt.removeAdvManufacturerCodeAndData(manufacturerCode);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ }
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index a2bb78c..cd093c5 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -553,14 +553,6 @@
Log.w(TAG, "Unhandled exception in callback", ex);
}
}
-
- /**
- * Listen command status callback
- * @hide
- */
- public void onListen(int status) {
- if (DBG) Log.d(TAG, "onListen() - status=" + status);
- }
};
/*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device) {
@@ -693,71 +685,6 @@
return true;
}
- /**
- * Starts or stops sending of advertisement packages to listen for connection
- * requests from a central devices.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param start Start or stop advertising
- */
- /*package*/ void listen(boolean start) {
- if (mContext == null || !mContext.getResources().
- getBoolean(com.android.internal.R.bool.config_bluetooth_le_peripheral_mode_supported)) {
- throw new UnsupportedOperationException("BluetoothGatt#listen is blocked");
- }
- if (DBG) Log.d(TAG, "listen() - start: " + start);
- if (mService == null || mClientIf == 0) return;
-
- try {
- mService.clientListen(mClientIf, start);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
- }
-
- /**
- * Sets the advertising data contained in the adv. response packet.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param advData true to set adv. data, false to set scan response
- * @param includeName Inlucde the name in the adv. response
- * @param includeTxPower Include TX power value
- * @param minInterval Minimum desired scan interval (optional)
- * @param maxInterval Maximum desired scan interval (optional)
- * @param appearance The appearance flags for the device (optional)
- * @param manufacturerData Manufacturer specific data including company ID (optional)
- */
- /*package*/ void setAdvData(boolean advData, boolean includeName, boolean includeTxPower,
- Integer minInterval, Integer maxInterval,
- Integer appearance, Byte[] manufacturerData) {
- if (mContext == null || !mContext.getResources().
- getBoolean(com.android.internal.R.bool.config_bluetooth_le_peripheral_mode_supported)) {
- throw new UnsupportedOperationException("BluetoothGatt#setAdvData is blocked");
- }
- if (DBG) Log.d(TAG, "setAdvData()");
- if (mService == null || mClientIf == 0) return;
-
- byte[] data = new byte[0];
- if (manufacturerData != null) {
- data = new byte[manufacturerData.length];
- for(int i = 0; i != manufacturerData.length; ++i) {
- data[i] = manufacturerData[i];
- }
- }
-
- try {
- mService.setAdvData(mClientIf, !advData,
- includeName, includeTxPower,
- minInterval != null ? minInterval : 0,
- maxInterval != null ? maxInterval : 0,
- appearance != null ? appearance : 0, data);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
- }
-
/**
* Disconnects an established connection, or cancels a connection attempt
* currently in progress.
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 58ee54f..153215c 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -537,7 +537,7 @@
try {
mService.beginServiceDeclaration(mServerIf, service.getType(),
service.getInstanceId(), service.getHandles(),
- new ParcelUuid(service.getUuid()));
+ new ParcelUuid(service.getUuid()), service.isAdvertisePreferred());
List<BluetoothGattService> includedServices = service.getIncludedServices();
for (BluetoothGattService includedService : includedServices) {
diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java
index 1e66369..52bc0f7 100644
--- a/core/java/android/bluetooth/BluetoothGattService.java
+++ b/core/java/android/bluetooth/BluetoothGattService.java
@@ -15,8 +15,6 @@
*/
package android.bluetooth;
-import android.bluetooth.BluetoothDevice;
-
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@@ -82,6 +80,11 @@
protected List<BluetoothGattService> mIncludedServices;
/**
+ * Whether the service uuid should be advertised.
+ */
+ private boolean mAdvertisePreferred;
+
+ /**
* Create a new BluetoothGattService.
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
@@ -263,4 +266,20 @@
}
return null;
}
+
+ /**
+ * Returns whether the uuid of the service should be advertised.
+ * @hide
+ */
+ public boolean isAdvertisePreferred() {
+ return mAdvertisePreferred;
+ }
+
+ /**
+ * Set whether the service uuid should be advertised.
+ * @hide
+ */
+ public void setAdvertisePreferred(boolean advertisePreferred) {
+ this.mAdvertisePreferred = advertisePreferred;
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index abdf949e..4b28516 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -73,6 +73,9 @@
public static final ParcelUuid MAS =
ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB");
+ public static final ParcelUuid BASE_UUID =
+ ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB");
+
public static final ParcelUuid[] RESERVED_UUIDS = {
AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget,
@@ -211,4 +214,17 @@
long value = (uuid.getMostSignificantBits() & 0x0000FFFF00000000L) >>> 32;
return (int)value;
}
+
+ /**
+ * Check whether the given parcelUuid can be converted to 16 bit bluetooth uuid.
+ * @param parcelUuid
+ * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise.
+ */
+ public static boolean isShortUuid(ParcelUuid parcelUuid) {
+ UUID uuid = parcelUuid.getUuid();
+ if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) {
+ return false;
+ }
+ return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L);
+ }
}
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index df393db..784cdcc 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -37,10 +37,15 @@
void unregisterClient(in int clientIf);
void clientConnect(in int clientIf, in String address, in boolean isDirect);
void clientDisconnect(in int clientIf, in String address);
- void clientListen(in int clientIf, in boolean start);
- void setAdvData(in int clientIf, in boolean setScanRsp, in boolean inclName,
- in boolean inclTxPower, in int minInterval, in int maxInterval,
- in int appearance, in byte[] manufacturerData);
+ void startAdvertising(in int appIf);
+ void stopAdvertising();
+ boolean setAdvServiceData(in byte[] serviceData);
+ byte[] getAdvServiceData();
+ boolean setAdvManufacturerCodeAndData(int manufactureCode, in byte[] manufacturerData);
+ byte[] getAdvManufacturerData();
+ List<ParcelUuid> getAdvServiceUuids();
+ void removeAdvManufacturerCodeAndData(int manufacturerCode);
+ boolean isAdvertising();
void refreshDevice(in int clientIf, in String address);
void discoverServices(in int clientIf, in String address);
void readCharacteristic(in int clientIf, in String address, in int srvcType,
@@ -75,7 +80,7 @@
void serverDisconnect(in int serverIf, in String address);
void beginServiceDeclaration(in int serverIf, in int srvcType,
in int srvcInstanceId, in int minHandles,
- in ParcelUuid srvcId);
+ in ParcelUuid srvcId, boolean advertisePreferred);
void addIncludedService(in int serverIf, in int srvcType,
in int srvcInstanceId, in ParcelUuid srvcId);
void addCharacteristic(in int serverIf, in ParcelUuid charId,
diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
index 60c297b..e3563fc 100644
--- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
@@ -63,5 +63,4 @@
in int charInstId, in ParcelUuid charUuid,
in byte[] value);
void onReadRemoteRssi(in String address, in int rssi, in int status);
- void onListen(in int status);
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index bc0d7e3..d779628 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -232,8 +232,6 @@
InputStage mFirstInputStage;
InputStage mFirstPostImeInputStage;
- boolean mFlipControllerFallbackKeys;
-
boolean mWindowAttributesChanged = false;
int mWindowAttributesChangesFlag = 0;
@@ -370,8 +368,6 @@
mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
mFallbackEventHandler = PolicyManager.makeNewFallbackEventHandler(context);
mChoreographer = Choreographer.getInstance();
- mFlipControllerFallbackKeys =
- context.getResources().getBoolean(R.bool.flip_controller_fallback_keys);
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mAttachInfo.mScreenOn = powerManager.isScreenOn();
@@ -2912,11 +2908,8 @@
mView.dispatchConfigurationChanged(config);
}
}
-
- mFlipControllerFallbackKeys =
- mContext.getResources().getBoolean(R.bool.flip_controller_fallback_keys);
}
-
+
/**
* Return true if child is an ancestor of parent, (or equal to the parent).
*/
@@ -3985,7 +3978,6 @@
private final SyntheticJoystickHandler mJoystick = new SyntheticJoystickHandler();
private final SyntheticTouchNavigationHandler mTouchNavigation =
new SyntheticTouchNavigationHandler();
- private final SyntheticKeyHandler mKeys = new SyntheticKeyHandler();
public SyntheticInputStage() {
super(null);
@@ -4008,12 +4000,7 @@
mTouchNavigation.process(event);
return FINISH_HANDLED;
}
- } else if (q.mEvent instanceof KeyEvent) {
- if (mKeys.process((KeyEvent) q.mEvent)) {
- return FINISH_HANDLED;
- }
}
-
return FORWARD;
}
@@ -4843,63 +4830,6 @@
};
}
- final class SyntheticKeyHandler {
-
- public boolean process(KeyEvent event) {
- // In some locales (like Japan) controllers use B for confirm and A for back, rather
- // than vice versa, so we need to special case this here since the input system itself
- // is not locale-aware.
- int keyCode;
- switch(event.getKeyCode()) {
- case KeyEvent.KEYCODE_BUTTON_A:
- case KeyEvent.KEYCODE_BUTTON_C:
- case KeyEvent.KEYCODE_BUTTON_X:
- case KeyEvent.KEYCODE_BUTTON_Z:
- keyCode = mFlipControllerFallbackKeys ?
- KeyEvent.KEYCODE_BACK : KeyEvent.KEYCODE_DPAD_CENTER;
- break;
- case KeyEvent.KEYCODE_BUTTON_B:
- case KeyEvent.KEYCODE_BUTTON_Y:
- keyCode = mFlipControllerFallbackKeys ?
- KeyEvent.KEYCODE_DPAD_CENTER : KeyEvent.KEYCODE_BACK;
- break;
- case KeyEvent.KEYCODE_BUTTON_THUMBL:
- case KeyEvent.KEYCODE_BUTTON_THUMBR:
- case KeyEvent.KEYCODE_BUTTON_START:
- case KeyEvent.KEYCODE_BUTTON_1:
- case KeyEvent.KEYCODE_BUTTON_2:
- case KeyEvent.KEYCODE_BUTTON_3:
- case KeyEvent.KEYCODE_BUTTON_4:
- case KeyEvent.KEYCODE_BUTTON_5:
- case KeyEvent.KEYCODE_BUTTON_6:
- case KeyEvent.KEYCODE_BUTTON_7:
- case KeyEvent.KEYCODE_BUTTON_8:
- case KeyEvent.KEYCODE_BUTTON_9:
- case KeyEvent.KEYCODE_BUTTON_10:
- case KeyEvent.KEYCODE_BUTTON_11:
- case KeyEvent.KEYCODE_BUTTON_12:
- case KeyEvent.KEYCODE_BUTTON_13:
- case KeyEvent.KEYCODE_BUTTON_14:
- case KeyEvent.KEYCODE_BUTTON_15:
- case KeyEvent.KEYCODE_BUTTON_16:
- keyCode = KeyEvent.KEYCODE_DPAD_CENTER;
- break;
- case KeyEvent.KEYCODE_BUTTON_SELECT:
- case KeyEvent.KEYCODE_BUTTON_MODE:
- keyCode = KeyEvent.KEYCODE_MENU;
- default:
- return false;
- }
-
- enqueueInputEvent(new KeyEvent(event.getDownTime(), event.getEventTime(),
- event.getAction(), keyCode, event.getRepeatCount(), event.getMetaState(),
- event.getDeviceId(), event.getScanCode(),
- event.getFlags() | KeyEvent.FLAG_FALLBACK, event.getSource()));
- return true;
- }
-
- }
-
/**
* Returns true if the key is used for keyboard navigation.
* @param keyEvent The key event.
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 5392a96..6a369a6 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -308,6 +308,11 @@
mMirrorForRtl = a.getBoolean(R.styleable.ProgressBar_mirrorForRtl, mMirrorForRtl);
a.recycle();
+
+ // If not explicitly specified this view is important for accessibility.
+ if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
+ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+ }
}
/**
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index b204dfd..1cda631 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -731,10 +731,14 @@
}
}
- if (scheduleOtherSpellCheck) {
+ if (scheduleOtherSpellCheck && wordStart <= end) {
// Update range span: start new spell check from last wordStart
setRangeSpan(editable, wordStart, end);
} else {
+ if (DBG && scheduleOtherSpellCheck) {
+ Log.w(TAG, "Trying to schedule spellcheck for invalid region, from "
+ + wordStart + " to " + end);
+ }
removeRangeSpan(editable);
}
diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index 0cad33c..0aad0b5 100644
--- a/core/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -1004,7 +1004,7 @@
for (int iproc=pkgState.mProcesses.size()-1; iproc>=0; iproc--) {
ProcessState ps = pkgState.mProcesses.valueAt(iproc);
if (ps.isInUse() || ps.mCommonProcess.isInUse()) {
- pkgState.mProcesses.valueAt(iproc).resetSafely(now);
+ ps.resetSafely(now);
} else {
pkgState.mProcesses.valueAt(iproc).makeDead();
pkgState.mProcesses.removeAt(iproc);
@@ -1013,7 +1013,7 @@
for (int isvc=pkgState.mServices.size()-1; isvc>=0; isvc--) {
ServiceState ss = pkgState.mServices.valueAt(isvc);
if (ss.isInUse()) {
- pkgState.mServices.valueAt(isvc).resetSafely(now);
+ ss.resetSafely(now);
} else {
pkgState.mServices.removeAt(isvc);
}
@@ -3014,7 +3014,7 @@
}
public boolean isInUse() {
- return mOwner != null;
+ return mOwner != null || mRestarting;
}
void add(ServiceState other) {
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 4654178..fe1cf72 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -164,8 +164,24 @@
}
actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE);
+ final ActionMenuView menuParent = (ActionMenuView) parent;
+ final ViewGroup.LayoutParams lp = actionView.getLayoutParams();
+ if (!menuParent.checkLayoutParams(lp)) {
+ actionView.setLayoutParams(menuParent.generateLayoutParams(lp));
+ }
+ return actionView;
+ }
+
+ @Override
+ public void bindItemView(final MenuItemImpl item, MenuView.ItemView itemView) {
+ itemView.initialize(item, 0);
+
+ final ActionMenuView menuView = (ActionMenuView) mMenuView;
+ final ActionMenuItemView actionItemView = (ActionMenuItemView) itemView;
+ actionItemView.setItemInvoker(menuView);
+
if (item.hasSubMenu()) {
- actionView.setOnTouchListener(new ForwardingListener(actionView) {
+ actionItemView.setOnTouchListener(new ForwardingListener(actionItemView) {
@Override
public ListPopupWindow getPopup() {
return mActionButtonPopup != null ? mActionButtonPopup.getPopup() : null;
@@ -182,24 +198,8 @@
}
});
} else {
- actionView.setOnTouchListener(null);
+ actionItemView.setOnTouchListener(null);
}
-
- final ActionMenuView menuParent = (ActionMenuView) parent;
- final ViewGroup.LayoutParams lp = actionView.getLayoutParams();
- if (!menuParent.checkLayoutParams(lp)) {
- actionView.setLayoutParams(menuParent.generateLayoutParams(lp));
- }
- return actionView;
- }
-
- @Override
- public void bindItemView(MenuItemImpl item, MenuView.ItemView itemView) {
- itemView.initialize(item, 0);
-
- final ActionMenuView menuView = (ActionMenuView) mMenuView;
- ActionMenuItemView actionItemView = (ActionMenuItemView) itemView;
- actionItemView.setItemInvoker(menuView);
}
@Override
diff --git a/core/java/com/android/internal/view/menu/ListMenuPresenter.java b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
index 4882adc..e1bb3621 100644
--- a/core/java/com/android/internal/view/menu/ListMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
@@ -163,7 +163,7 @@
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- mMenu.performItemAction(mAdapter.getItem(position), 0);
+ mMenu.performItemAction(mAdapter.getItem(position), this, 0);
}
@Override
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index aff697a..195a00d 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -247,11 +247,17 @@
startDispatchingItemsChanged();
}
- private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu) {
+ private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu,
+ MenuPresenter preferredPresenter) {
if (mPresenters.isEmpty()) return false;
boolean result = false;
+ // Try the preferred presenter first.
+ if (preferredPresenter != null) {
+ result = preferredPresenter.onSubMenuSelected(subMenu);
+ }
+
for (WeakReference<MenuPresenter> ref : mPresenters) {
final MenuPresenter presenter = ref.get();
if (presenter == null) {
@@ -865,6 +871,10 @@
}
public boolean performItemAction(MenuItem item, int flags) {
+ return performItemAction(item, null, flags);
+ }
+
+ public boolean performItemAction(MenuItem item, MenuPresenter preferredPresenter, int flags) {
MenuItemImpl itemImpl = (MenuItemImpl) item;
if (itemImpl == null || !itemImpl.isEnabled()) {
@@ -889,7 +899,7 @@
if (providerHasSubMenu) {
provider.onPrepareSubMenu(subMenu);
}
- invoked |= dispatchSubMenuSelected(subMenu);
+ invoked |= dispatchSubMenuSelected(subMenu, preferredPresenter);
if (!invoked) close(true);
} else {
if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) {
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index eea9ee1..2125763 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -227,7 +227,7 @@
do {
*dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
} while (--width != 0);
- ctable->unlockColors(false);
+ ctable->unlockColors();
}
static void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
@@ -240,7 +240,7 @@
*dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
SkGetPackedG32(c), SkGetPackedB32(c));
} while (--width != 0);
- ctable->unlockColors(false);
+ ctable->unlockColors();
}
static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
@@ -253,7 +253,7 @@
*dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
SkGetPackedB32(c));
} while (--width != 0);
- ctable->unlockColors(false);
+ ctable->unlockColors();
}
// can return NULL
@@ -442,9 +442,15 @@
return !bitmap->isOpaque();
}
-static void Bitmap_setHasAlpha(JNIEnv* env, jobject, SkBitmap* bitmap,
- jboolean hasAlpha) {
- bitmap->setIsOpaque(!hasAlpha);
+static void Bitmap_setAlphaAndPremultiplied(JNIEnv* env, jobject, SkBitmap* bitmap,
+ jboolean hasAlpha, jboolean isPremul) {
+ if (!hasAlpha) {
+ bitmap->setAlphaType(kOpaque_SkAlphaType);
+ } else if (isPremul) {
+ bitmap->setAlphaType(kPremul_SkAlphaType);
+ } else {
+ bitmap->setAlphaType(kUnpremul_SkAlphaType);
+ }
}
static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, SkBitmap* bitmap) {
@@ -543,14 +549,14 @@
p->writeInt32(bitmap->rowBytes());
p->writeInt32(density);
- if (bitmap->getConfig() == SkBitmap::kIndex8_Config) {
+ if (bitmap->config() == SkBitmap::kIndex8_Config) {
SkColorTable* ctable = bitmap->getColorTable();
if (ctable != NULL) {
int count = ctable->count();
p->writeInt32(count);
memcpy(p->writeInplace(count * sizeof(SkPMColor)),
ctable->lockColors(), count * sizeof(SkPMColor));
- ctable->unlockColors(false);
+ ctable->unlockColors();
} else {
p->writeInt32(0); // indicate no ctable
}
@@ -770,7 +776,7 @@
{ "nativeRowBytes", "(I)I", (void*)Bitmap_rowBytes },
{ "nativeConfig", "(I)I", (void*)Bitmap_config },
{ "nativeHasAlpha", "(I)Z", (void*)Bitmap_hasAlpha },
- { "nativeSetHasAlpha", "(IZ)V", (void*)Bitmap_setHasAlpha },
+ { "nativeSetAlphaAndPremultiplied", "(IZZ)V", (void*)Bitmap_setAlphaAndPremultiplied},
{ "nativeHasMipMap", "(I)Z", (void*)Bitmap_hasMipMap },
{ "nativeSetHasMipMap", "(IZ)V", (void*)Bitmap_setHasMipMap },
{ "nativeCreateFromParcel",
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index da6219f..709de5c 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -21,6 +21,7 @@
#include <androidfw/Asset.h>
#include <androidfw/ResourceTypes.h>
#include <netinet/in.h>
+#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
@@ -124,12 +125,18 @@
static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStreamRewindable* stream,
int sampleSize, bool ditherImage) {
+ SkImageInfo bitmapInfo;
+ if (!bitmap->asImageInfo(&bitmapInfo)) {
+ ALOGW("bitmap has unknown configuration so no memory has been allocated");
+ return NULL;
+ }
+
SkImageRef* pr;
// only use ashmem for large images, since mmaps come at a price
if (bitmap->getSize() >= 32 * 1024) {
- pr = new SkImageRef_ashmem(stream, bitmap->config(), sampleSize);
+ pr = new SkImageRef_ashmem(bitmapInfo, stream, sampleSize);
} else {
- pr = new SkImageRef_GlobalPool(stream, bitmap->config(), sampleSize);
+ pr = new SkImageRef_GlobalPool(bitmapInfo, stream, sampleSize);
}
pr->setDitherImage(ditherImage);
bitmap->setPixelRef(pr)->unref();
@@ -157,7 +164,7 @@
virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
// accounts for scale in final allocation, using eventual size and config
const int bytesPerPixel = SkBitmap::ComputeBytesPerPixel(
- configForScaledOutput(bitmap->getConfig()));
+ configForScaledOutput(bitmap->config()));
const int requestedSize = bytesPerPixel *
int(bitmap->width() * mScale + 0.5f) *
int(bitmap->height() * mScale + 0.5f);
@@ -191,8 +198,15 @@
return false;
}
+ SkImageInfo bitmapInfo;
+ if (!bitmap->asImageInfo(&bitmapInfo)) {
+ ALOGW("unable to reuse a bitmap as the target has an unknown bitmap configuration");
+ return false;
+ }
+
// Create a new pixelref with the new ctable that wraps the previous pixelref
- SkPixelRef* pr = new AndroidPixelRef(*static_cast<AndroidPixelRef*>(mPixelRef), ctable);
+ SkPixelRef* pr = new AndroidPixelRef(*static_cast<AndroidPixelRef*>(mPixelRef),
+ bitmapInfo, bitmap->rowBytes(), ctable);
bitmap->setPixelRef(pr)->unref();
// since we're already allocated, we lockPixels right away
@@ -401,8 +415,11 @@
// TODO: avoid copying when scaled size equals decodingBitmap size
SkBitmap::Config config = configForScaledOutput(decodingBitmap.config());
- outputBitmap->setConfig(config, scaledWidth, scaledHeight);
- outputBitmap->setIsOpaque(decodingBitmap.isOpaque());
+ // FIXME: If the alphaType is kUnpremul and the image has alpha, the
+ // colors may not be correct, since Skia does not yet support drawing
+ // to/from unpremultiplied bitmaps.
+ outputBitmap->setConfig(config, scaledWidth, scaledHeight, 0,
+ decodingBitmap.alphaType());
if (!outputBitmap->allocPixels(outputAllocator, NULL)) {
return nullObjectReturn("allocation failed for scaled bitmap");
}
@@ -414,7 +431,7 @@
}
SkPaint paint;
- paint.setFilterBitmap(true);
+ paint.setFilterLevel(SkPaint::kLow_FilterLevel);
SkCanvas canvas(*outputBitmap);
canvas.scale(sx, sy);
@@ -470,6 +487,12 @@
bitmapCreateFlags, ninePatchChunk, layoutBounds, -1);
}
+// Need to buffer enough input to be able to rewind as much as might be read by a decoder
+// trying to determine the stream's format. Currently the most is 64, read by
+// SkImageDecoder_libwebp.
+// FIXME: Get this number from SkImageDecoder
+#define BYTES_TO_BUFFER 64
+
static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage,
jobject padding, jobject options) {
@@ -477,11 +500,8 @@
SkAutoTUnref<SkStream> stream(CreateJavaInputStreamAdaptor(env, is, storage));
if (stream.get()) {
- // Need to buffer enough input to be able to rewind as much as might be read by a decoder
- // trying to determine the stream's format. Currently the most is 64, read by
- // SkImageDecoder_libwebp.
- // FIXME: Get this number from SkImageDecoder
- SkAutoTUnref<SkStreamRewindable> bufferedStream(SkFrontBufferedStream::Create(stream, 64));
+ SkAutoTUnref<SkStreamRewindable> bufferedStream(
+ SkFrontBufferedStream::Create(stream, BYTES_TO_BUFFER));
SkASSERT(bufferedStream.get() != NULL);
// for now we don't allow purgeable with java inputstreams
bitmap = doDecode(env, bufferedStream, padding, options, false, false);
@@ -502,27 +522,48 @@
return nullObjectReturn("fstat return -1");
}
- bool isPurgeable = optionsPurgeable(env, bitmapFactoryOptions);
- bool isShareable = optionsShareable(env, bitmapFactoryOptions);
- bool weOwnTheFD = false;
- if (isPurgeable && isShareable) {
- int newFD = ::dup(descriptor);
- if (-1 != newFD) {
- weOwnTheFD = true;
- descriptor = newFD;
+ // Restore the descriptor's offset on exiting this function.
+ AutoFDSeek autoRestore(descriptor);
+
+ FILE* file = fdopen(descriptor, "r");
+ if (file == NULL) {
+ return nullObjectReturn("Could not open file");
+ }
+
+ SkAutoTUnref<SkFILEStream> fileStream(new SkFILEStream(file,
+ SkFILEStream::kCallerRetains_Ownership));
+
+ SkAutoTUnref<SkStreamRewindable> stream;
+
+ // Retain the old behavior of allowing purgeable if both purgeable and
+ // shareable are set to true.
+ bool isPurgeable = optionsPurgeable(env, bitmapFactoryOptions)
+ && optionsShareable(env, bitmapFactoryOptions);
+ if (isPurgeable) {
+ // Copy the stream, so the image can be decoded multiple times without
+ // continuing to modify the original file descriptor.
+ // Copy beginning from the current position.
+ const size_t fileSize = fileStream->getLength() - fileStream->getPosition();
+ void* buffer = sk_malloc_flags(fileSize, 0);
+ if (buffer == NULL) {
+ return nullObjectReturn("Could not make a copy for ashmem");
}
+
+ SkAutoTUnref<SkData> data(SkData::NewFromMalloc(buffer, fileSize));
+
+ if (fileStream->read(buffer, fileSize) != fileSize) {
+ return nullObjectReturn("Could not read the file.");
+ }
+
+ stream.reset(new SkMemoryStream(data));
+ } else {
+ // Use a buffered stream. Although an SkFILEStream can be rewound, this
+ // ensures that SkImageDecoder::Factory never rewinds beyond the
+ // current position of the file descriptor.
+ stream.reset(SkFrontBufferedStream::Create(fileStream, BYTES_TO_BUFFER));
}
- SkAutoTUnref<SkData> data(SkData::NewFromFD(descriptor));
- if (data.get() == NULL) {
- return nullObjectReturn("NewFromFD failed in nativeDecodeFileDescriptor");
- }
- SkAutoTUnref<SkMemoryStream> stream(new SkMemoryStream(data));
-
- /* Allow purgeable iff we own the FD, i.e., in the puregeable and
- shareable case.
- */
- return doDecode(env, stream, padding, bitmapFactoryOptions, weOwnTheFD);
+ return doDecode(env, stream, padding, bitmapFactoryOptions, isPurgeable);
}
static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jint native_asset,
@@ -541,7 +582,9 @@
} else {
// since we know we'll be done with the asset when we return, we can
// just use a simple wrapper
- stream = new AssetStreamAdaptor(asset);
+ stream = new AssetStreamAdaptor(asset,
+ AssetStreamAdaptor::kNo_OwnAsset,
+ AssetStreamAdaptor::kNo_HasMemoryBase);
}
SkAutoUnref aur(stream);
return doDecode(env, stream, padding, options, forcePurgeable, forcePurgeable);
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index ee47ac4..1412a0e 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -29,7 +29,6 @@
#include "CreateJavaOutputStreamAdaptor.h"
#include "Utils.h"
#include "JNIHelp.h"
-#include "SkTScopedPtr.h"
#include <android_runtime/AndroidRuntime.h>
#include "android_util_Binder.h"
@@ -76,7 +75,7 @@
int fHeight;
};
-static jobject createBitmapRegionDecoder(JNIEnv* env, SkStream* stream) {
+static jobject createBitmapRegionDecoder(JNIEnv* env, SkStreamRewindable* stream) {
SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
int width, height;
if (NULL == decoder) {
@@ -108,7 +107,7 @@
For now we just always copy the array's data if isShareable.
*/
AutoJavaByteArray ar(env, byteArray);
- SkStream* stream = new SkMemoryStream(ar.ptr() + offset, length, true);
+ SkStreamRewindable* stream = new SkMemoryStream(ar.ptr() + offset, length, true);
jobject brd = createBitmapRegionDecoder(env, stream);
SkSafeUnref(stream); // the decoder now holds a reference
@@ -215,7 +214,7 @@
region.fRight = start_x + width;
region.fBottom = start_y + height;
SkBitmap* bitmap = NULL;
- SkTScopedPtr<SkBitmap> adb;
+ SkAutoTDelete<SkBitmap> adb;
if (tileBitmap != NULL) {
// Re-use bitmap.
@@ -246,7 +245,7 @@
}
// detach bitmap from its autodeleter, since we want to own it now
- adb.release();
+ adb.detach();
JavaPixelAllocator* allocator = (JavaPixelAllocator*) decoder->getAllocator();
jbyteArray buff = allocator->getStorageObjAndReset();
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 813dd5a..edf3b4a 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -476,7 +476,7 @@
if (paint) {
filteredPaint = *paint;
}
- filteredPaint.setFilterBitmap(true);
+ filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
canvas->drawBitmap(*bitmap, left_, top_, &filteredPaint);
} else {
canvas->drawBitmap(*bitmap, left_, top_, paint);
@@ -491,7 +491,7 @@
if (paint) {
filteredPaint = *paint;
}
- filteredPaint.setFilterBitmap(true);
+ filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
@@ -514,7 +514,7 @@
if (paint) {
filteredPaint = *paint;
}
- filteredPaint.setFilterBitmap(true);
+ filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
canvas->drawBitmapRect(*bitmap, srcPtr, dst, &filteredPaint);
} else {
canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 8cb152d..3090ad2 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -346,6 +346,18 @@
///////////////////////////////////////////////////////////////////////////////////////////
+// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
+static void assert_premultiplied(const SkBitmap& bitmap, bool isPremultiplied) {
+ // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
+ // irrelevant. This just tests to ensure that the SkAlphaType is not
+ // opposite of isPremultiplied.
+ if (isPremultiplied) {
+ SkASSERT(bitmap.alphaType() != kUnpremul_SkAlphaType);
+ } else {
+ SkASSERT(bitmap.alphaType() != kPremul_SkAlphaType);
+ }
+}
+
jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
int bitmapCreateFlags, jbyteArray ninepatch, jintArray layoutbounds, int density)
{
@@ -354,6 +366,10 @@
bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
+ // The caller needs to have already set the alpha type properly, so the
+ // native SkBitmap stays in sync with the Java Bitmap.
+ assert_premultiplied(*bitmap, isPremultiplied);
+
jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
static_cast<jint>(reinterpret_cast<uintptr_t>(bitmap)), buffer,
bitmap->width(), bitmap->height(), density, isMutable, isPremultiplied,
@@ -371,6 +387,10 @@
void GraphicsJNI::reinitBitmap(JNIEnv* env, jobject javaBitmap, SkBitmap* bitmap,
bool isPremultiplied)
{
+ // The caller needs to have already set the alpha type properly, so the
+ // native SkBitmap stays in sync with the Java Bitmap.
+ assert_premultiplied(*bitmap, isPremultiplied);
+
env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
bitmap->width(), bitmap->height(), isPremultiplied);
}
@@ -413,8 +433,9 @@
///////////////////////////////////////////////////////////////////////////////
-AndroidPixelRef::AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj,
- SkColorTable* ctable) : SkMallocPixelRef(storage, size, ctable, (storageObj == NULL)),
+AndroidPixelRef::AndroidPixelRef(JNIEnv* env, const SkImageInfo& info, void* storage,
+ size_t rowBytes, jbyteArray storageObj, SkColorTable* ctable) :
+ SkMallocPixelRef(info, storage, rowBytes, ctable, (storageObj == NULL)),
fWrappedPixelRef(NULL) {
SkASSERT(storage);
SkASSERT(env);
@@ -429,13 +450,13 @@
// If storageObj is NULL, the memory was NOT allocated on the Java heap
fOnJavaHeap = (storageObj != NULL);
-
}
-AndroidPixelRef::AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, SkColorTable* ctable) :
- SkMallocPixelRef(wrappedPixelRef.getAddr(), wrappedPixelRef.getSize(), ctable, false),
+AndroidPixelRef::AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, const SkImageInfo& info,
+ size_t rowBytes, SkColorTable* ctable) :
+ SkMallocPixelRef(info, wrappedPixelRef.getAddr(), rowBytes, ctable, false),
fWrappedPixelRef(wrappedPixelRef.fWrappedPixelRef ?
- wrappedPixelRef.fWrappedPixelRef : &wrappedPixelRef)
+ wrappedPixelRef.fWrappedPixelRef : &wrappedPixelRef)
{
SkASSERT(fWrappedPixelRef);
SkSafeRef(fWrappedPixelRef);
@@ -540,13 +561,21 @@
return NULL;
}
+ SkImageInfo bitmapInfo;
+ if (!bitmap->asImageInfo(&bitmapInfo)) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "unknown bitmap configuration");
+ return NULL;
+ }
+
size_t size = size64.get32();
jbyteArray arrayObj = env->NewByteArray(size);
if (arrayObj) {
// TODO: make this work without jniGetNonMovableArrayElements
jbyte* addr = jniGetNonMovableArrayElements(&env->functions, arrayObj);
if (addr) {
- SkPixelRef* pr = new AndroidPixelRef(env, (void*) addr, size, arrayObj, ctable);
+ SkPixelRef* pr = new AndroidPixelRef(env, bitmapInfo, (void*) addr,
+ bitmap->rowBytes(), arrayObj, ctable);
bitmap->setPixelRef(pr)->unref();
// since we're already allocated, we lockPixels right away
// HeapAllocator behaves this way too
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index f4590b9..cb154aa 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -57,6 +57,7 @@
/** Create a java Bitmap object given the native bitmap (required) and optional
storage array (may be null).
+ bitmap's SkAlphaType must already be in sync with bitmapCreateFlags.
*/
static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
int bitmapCreateFlags, jbyteArray ninepatch, jintArray layoutbounds, int density = -1);
@@ -64,6 +65,9 @@
static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, int bitmapCreateFlags,
jbyteArray ninepatch, int density = -1);
+ /** Reinitialize a bitmap. bitmap must already have its SkAlphaType set in
+ sync with isPremultiplied
+ */
static void reinitBitmap(JNIEnv* env, jobject javaBitmap, SkBitmap* bitmap,
bool isPremultiplied);
@@ -88,15 +92,16 @@
class AndroidPixelRef : public SkMallocPixelRef {
public:
- AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj,
- SkColorTable* ctable);
+ AndroidPixelRef(JNIEnv* env, const SkImageInfo& info, void* storage, size_t rowBytes,
+ jbyteArray storageObj, SkColorTable* ctable);
/**
* Creates an AndroidPixelRef that wraps (and refs) another to reuse/share
* the same storage and java byte array refcounting, yet have a different
* color table.
*/
- AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, SkColorTable* ctable);
+ AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, const SkImageInfo& info,
+ size_t rowBytes, SkColorTable* ctable);
virtual ~AndroidPixelRef();
diff --git a/core/jni/android/graphics/Movie.cpp b/core/jni/android/graphics/Movie.cpp
index feb2dec..55be7c1 100644
--- a/core/jni/android/graphics/Movie.cpp
+++ b/core/jni/android/graphics/Movie.cpp
@@ -85,7 +85,9 @@
static jobject movie_decodeAsset(JNIEnv* env, jobject clazz, jint native_asset) {
android::Asset* asset = reinterpret_cast<android::Asset*>(native_asset);
if (asset == NULL) return NULL;
- SkAutoTUnref<SkStreamRewindable> stream (new android::AssetStreamAdaptor(asset));
+ SkAutoTUnref<SkStreamRewindable> stream (new android::AssetStreamAdaptor(asset,
+ android::AssetStreamAdaptor::kNo_OwnAsset,
+ android::AssetStreamAdaptor::kNo_HasMemoryBase));
SkMovie* moov = SkMovie::DecodeStream(stream.get());
return create_jmovie(env, moov);
}
diff --git a/core/jni/android/graphics/NinePatchPeeker.cpp b/core/jni/android/graphics/NinePatchPeeker.cpp
index df996af..d3482da 100644
--- a/core/jni/android/graphics/NinePatchPeeker.cpp
+++ b/core/jni/android/graphics/NinePatchPeeker.cpp
@@ -40,15 +40,14 @@
// now update our host to force index or 32bit config
// 'cause we don't want 565 predithered, since as a 9patch, we know
// we will be stretched, and therefore we want to dither afterwards.
- static const SkBitmap::Config gNo565Pref[] = {
- SkBitmap::kIndex8_Config,
- SkBitmap::kIndex8_Config,
- SkBitmap::kARGB_8888_Config,
- SkBitmap::kARGB_8888_Config,
- SkBitmap::kARGB_8888_Config,
- SkBitmap::kARGB_8888_Config,
- };
- fHost->setPrefConfigTable(gNo565Pref);
+ SkImageDecoder::PrefConfigTable table;
+ table.fPrefFor_8Index_NoAlpha_src = SkBitmap::kIndex8_Config;
+ table.fPrefFor_8Index_YesAlpha_src = SkBitmap::kIndex8_Config;
+ table.fPrefFor_8Gray_src = SkBitmap::kARGB_8888_Config;
+ table.fPrefFor_8bpc_NoAlpha_src = SkBitmap::kARGB_8888_Config;
+ table.fPrefFor_8bpc_YesAlpha_src = SkBitmap::kARGB_8888_Config;
+
+ fHost->setPrefConfigTable(table);
} else if (strcmp("npLb", tag) == 0 && length == sizeof(int) * 4) {
fLayoutBounds = new int[4];
memcpy(fLayoutBounds, data, sizeof(int) * 4);
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 40e0731..4f6cc37 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -148,7 +148,8 @@
static void setFilterBitmap(JNIEnv* env, jobject paint, jboolean filterBitmap) {
NPE_CHECK_RETURN_VOID(env, paint);
- GraphicsJNI::getNativePaint(env, paint)->setFilterBitmap(filterBitmap);
+ GraphicsJNI::getNativePaint(env, paint)->setFilterLevel(
+ filterBitmap ? SkPaint::kLow_FilterLevel : SkPaint::kNone_FilterLevel);
}
static void setDither(JNIEnv* env, jobject paint, jboolean dither) {
diff --git a/core/jni/android/graphics/Region.cpp b/core/jni/android/graphics/Region.cpp
index ded2186..f0a7baf 100644
--- a/core/jni/android/graphics/Region.cpp
+++ b/core/jni/android/graphics/Region.cpp
@@ -177,7 +177,7 @@
SkRegion* region = new SkRegion;
size_t size = p->readInt32();
- region->readFromMemory(p->readInplace(size));
+ region->readFromMemory(p->readInplace(size), size);
return region;
}
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 92d253f..144ac39 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -20,6 +20,7 @@
#include "TextLayoutCache.h"
#include "TextLayout.h"
+#include "SkGlyphCache.h"
#include "SkTypeface_android.h"
#include "HarfBuzzNGFaceSkia.h"
#include <unicode/unistr.h>
@@ -757,8 +758,8 @@
outPos->add(ypos);
totalAdvance += xAdvance;
- // TODO: consider using glyph cache
- const SkGlyph& metrics = mShapingPaint.getGlyphMetrics(glyphId, NULL);
+ SkAutoGlyphCache autoCache(mShapingPaint, NULL, NULL);
+ const SkGlyph& metrics = autoCache.getCache()->getGlyphIDMetrics(glyphId);
outBounds->join(xpos + metrics.fLeft, ypos + metrics.fTop,
xpos + metrics.fLeft + metrics.fWidth, ypos + metrics.fTop + metrics.fHeight);
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index ccd75d5..d10a960 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -4,6 +4,7 @@
#include "GraphicsJNI.h"
#include "SkStream.h"
#include "SkTypeface.h"
+#include "Utils.h"
#include <android_runtime/android_util_AssetManager.h>
#include <androidfw/AssetManager.h>
@@ -73,65 +74,6 @@
return face->style();
}
-class AssetStream : public SkStream {
-public:
- AssetStream(Asset* asset, bool hasMemoryBase) : fAsset(asset)
- {
- fMemoryBase = hasMemoryBase ? fAsset->getBuffer(false) : NULL;
- }
-
- virtual ~AssetStream()
- {
- delete fAsset;
- }
-
- virtual const void* getMemoryBase()
- {
- return fMemoryBase;
- }
-
- virtual bool rewind()
- {
- off64_t pos = fAsset->seek(0, SEEK_SET);
- return pos != (off64_t)-1;
- }
-
- virtual size_t read(void* buffer, size_t size)
- {
- ssize_t amount;
-
- if (NULL == buffer)
- {
- if (0 == size) // caller is asking us for our total length
- return fAsset->getLength();
-
- // asset->seek returns new total offset
- // we want to return amount that was skipped
-
- off64_t oldOffset = fAsset->seek(0, SEEK_CUR);
- if (-1 == oldOffset)
- return 0;
- off64_t newOffset = fAsset->seek(size, SEEK_CUR);
- if (-1 == newOffset)
- return 0;
-
- amount = newOffset - oldOffset;
- }
- else
- {
- amount = fAsset->read(buffer, size);
- }
-
- if (amount < 0)
- amount = 0;
- return amount;
- }
-
-private:
- Asset* fAsset;
- const void* fMemoryBase;
-};
-
static SkTypeface* Typeface_createFromAsset(JNIEnv* env, jobject,
jobject jassetMgr,
jstring jpath) {
@@ -150,7 +92,9 @@
return NULL;
}
- SkStream* stream = new AssetStream(asset, true);
+ SkStream* stream = new AssetStreamAdaptor(asset,
+ AssetStreamAdaptor::kYes_OwnAsset,
+ AssetStreamAdaptor::kYes_HasMemoryBase);
SkTypeface* face = SkTypeface::CreateFromStream(stream);
// SkTypeFace::CreateFromStream calls ref() on the stream, so we
// need to unref it here or it won't be freed later on
diff --git a/core/jni/android/graphics/Utils.cpp b/core/jni/android/graphics/Utils.cpp
index b7d1f3a..eb416cb 100644
--- a/core/jni/android/graphics/Utils.cpp
+++ b/core/jni/android/graphics/Utils.cpp
@@ -19,6 +19,21 @@
using namespace android;
+AssetStreamAdaptor::AssetStreamAdaptor(Asset* asset, OwnAsset ownAsset,
+ HasMemoryBase hasMemoryBase)
+ : fAsset(asset)
+ , fMemoryBase(kYes_HasMemoryBase == hasMemoryBase ?
+ asset->getBuffer(false) : NULL)
+ , fOwnAsset(ownAsset)
+{
+}
+
+AssetStreamAdaptor::~AssetStreamAdaptor() {
+ if (kYes_OwnAsset == fOwnAsset) {
+ delete fAsset;
+ }
+}
+
bool AssetStreamAdaptor::rewind() {
off64_t pos = fAsset->seek(0, SEEK_SET);
if (pos == (off64_t)-1) {
diff --git a/core/jni/android/graphics/Utils.h b/core/jni/android/graphics/Utils.h
index a1ac72a..b90593c 100644
--- a/core/jni/android/graphics/Utils.h
+++ b/core/jni/android/graphics/Utils.h
@@ -28,16 +28,36 @@
class AssetStreamAdaptor : public SkStreamRewindable {
public:
- AssetStreamAdaptor(Asset* a) : fAsset(a) {}
+ // Enum passed to constructor. If set to kYes_OwnAsset,
+ // the passed in Asset will be deleted upon destruction.
+ enum OwnAsset {
+ kYes_OwnAsset,
+ kNo_OwnAsset,
+ };
+
+ // Enum passed to constructor. If set to kYes_HasMemoryBase,
+ // getMemoryBase will return the Asset's buffer.
+ enum HasMemoryBase {
+ kYes_HasMemoryBase,
+ kNo_HasMemoryBase,
+ };
+
+ AssetStreamAdaptor(Asset*, OwnAsset, HasMemoryBase);
+ ~AssetStreamAdaptor();
+
virtual bool rewind();
virtual size_t read(void* buffer, size_t size);
virtual bool hasLength() const { return true; }
virtual size_t getLength() const;
virtual bool isAtEnd() const;
+ virtual const void* getMemoryBase() { return fMemoryBase; }
+
virtual SkStreamRewindable* duplicate() const;
private:
- Asset* fAsset;
+ Asset* fAsset;
+ const void* const fMemoryBase;
+ const OwnAsset fOwnAsset;
};
/**
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index 44af199..4bb091d 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -632,7 +632,7 @@
SkBitmap const * nativeBitmap =
(SkBitmap const *)env->GetIntField(jbitmap, nativeBitmapID);
const SkBitmap& bitmap(*nativeBitmap);
- SkBitmap::Config config = bitmap.getConfig();
+ SkBitmap::Config config = bitmap.config();
return getInternalFormat(config);
}
@@ -642,7 +642,7 @@
SkBitmap const * nativeBitmap =
(SkBitmap const *)env->GetIntField(jbitmap, nativeBitmapID);
const SkBitmap& bitmap(*nativeBitmap);
- SkBitmap::Config config = bitmap.getConfig();
+ SkBitmap::Config config = bitmap.config();
return getType(config);
}
@@ -653,7 +653,7 @@
SkBitmap const * nativeBitmap =
(SkBitmap const *)env->GetIntField(jbitmap, nativeBitmapID);
const SkBitmap& bitmap(*nativeBitmap);
- SkBitmap::Config config = bitmap.getConfig();
+ SkBitmap::Config config = bitmap.config();
if (internalformat < 0) {
internalformat = getInternalFormat(config);
}
@@ -681,7 +681,7 @@
SkColorTable* ctable = bitmap.getColorTable();
memcpy(data, ctable->lockColors(), ctable->count() * sizeof(SkPMColor));
memcpy(pixels, p, size);
- ctable->unlockColors(false);
+ ctable->unlockColors();
glCompressedTexImage2D(target, level, internalformat, w, h, border, imageSize, data);
free(data);
} else {
@@ -702,7 +702,7 @@
SkBitmap const * nativeBitmap =
(SkBitmap const *)env->GetIntField(jbitmap, nativeBitmapID);
const SkBitmap& bitmap(*nativeBitmap);
- SkBitmap::Config config = bitmap.getConfig();
+ SkBitmap::Config config = bitmap.config();
if (format < 0) {
format = getInternalFormat(config);
if (format == GL_PALETTE8_RGBA8_OES)
diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp
index 1fe4b08..5b0a4b2 100644
--- a/core/jni/android_opengl_EGL14.cpp
+++ b/core/jni/android_opengl_EGL14.cpp
@@ -630,7 +630,7 @@
if (producer == NULL)
goto not_valid_surface;
- window = new android::Surface(producer);
+ window = new android::Surface(producer, true);
if (window == NULL)
goto not_valid_surface;
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 1868469..dd178d8 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -39,6 +39,7 @@
#include <SkCanvas.h>
#include <SkBitmap.h>
+#include <SkImage.h>
#include <SkRegion.h>
#include <utils/misc.h>
@@ -178,7 +179,8 @@
static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
/* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
we can map to SkBitmap::kARGB_8888_Config, and optionally call
- bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
+ bitmap.setAlphaType(kOpaque_SkAlphaType) on the resulting SkBitmap
+ (as an accelerator)
*/
switch (format) {
case PIXEL_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config;
@@ -234,7 +236,7 @@
ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
bitmap.setConfig(convertPixelFormat(outBuffer.format), outBuffer.width, outBuffer.height, bpr);
if (outBuffer.format == PIXEL_FORMAT_RGBX_8888) {
- bitmap.setIsOpaque(true);
+ bitmap.setAlphaType(kOpaque_SkAlphaType);
}
if (outBuffer.width > 0 && outBuffer.height > 0) {
bitmap.setPixels(outBuffer.bits);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 67eade8..b8d3c20 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -61,51 +61,21 @@
class ScreenshotPixelRef : public SkPixelRef {
public:
- ScreenshotPixelRef(SkColorTable* ctable) {
- fCTable = ctable;
- SkSafeRef(ctable);
+ ScreenshotPixelRef(const SkImageInfo& info, ScreenshotClient* screenshot) :
+ SkPixelRef(info),
+ mScreenshot(screenshot) {
setImmutable();
}
virtual ~ScreenshotPixelRef() {
- SkSafeUnref(fCTable);
- }
-
- status_t update(const sp<IBinder>& display, int width, int height,
- int minLayer, int maxLayer, bool allLayers) {
- status_t res = (width > 0 && height > 0)
- ? (allLayers
- ? mScreenshot.update(display, width, height)
- : mScreenshot.update(display, width, height, minLayer, maxLayer))
- : mScreenshot.update(display);
- if (res != NO_ERROR) {
- return res;
- }
-
- return NO_ERROR;
- }
-
- uint32_t getWidth() const {
- return mScreenshot.getWidth();
- }
-
- uint32_t getHeight() const {
- return mScreenshot.getHeight();
- }
-
- uint32_t getStride() const {
- return mScreenshot.getStride();
- }
-
- uint32_t getFormat() const {
- return mScreenshot.getFormat();
+ delete mScreenshot;
}
protected:
// overrides from SkPixelRef
virtual void* onLockPixels(SkColorTable** ct) {
- *ct = fCTable;
- return (void*)mScreenshot.getPixels();
+ *ct = NULL;
+ return (void*)mScreenshot->getPixels();
}
virtual void onUnlockPixels() {
@@ -113,8 +83,7 @@
SK_DECLARE_UNFLATTENABLE_OBJECT()
private:
- ScreenshotClient mScreenshot;
- SkColorTable* fCTable;
+ ScreenshotClient* mScreenshot;
typedef SkPixelRef INHERITED;
};
@@ -147,19 +116,6 @@
ctrl->decStrong((void *)nativeCreate);
}
-static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
- /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
- we can map to SkBitmap::kARGB_8888_Config, and optionally call
- bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
- */
- switch (format) {
- case PIXEL_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config;
- case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config;
- case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config;
- default: return SkBitmap::kNo_Config;
- }
-}
-
static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject displayTokenObj,
jint width, jint height, jint minLayer, jint maxLayer, bool allLayers) {
sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
@@ -167,26 +123,50 @@
return NULL;
}
- ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL);
- if (pixels->update(displayToken, width, height,
- minLayer, maxLayer, allLayers) != NO_ERROR) {
- delete pixels;
+ ScreenshotClient* screenshot = new ScreenshotClient();
+ status_t res = (width > 0 && height > 0)
+ ? (allLayers
+ ? screenshot->update(displayToken, width, height)
+ : screenshot->update(displayToken, width, height, minLayer, maxLayer))
+ : screenshot->update(displayToken);
+ if (res != NO_ERROR) {
+ delete screenshot;
return NULL;
}
- uint32_t w = pixels->getWidth();
- uint32_t h = pixels->getHeight();
- uint32_t s = pixels->getStride();
- uint32_t f = pixels->getFormat();
- ssize_t bpr = s * android::bytesPerPixel(f);
+ SkImageInfo screenshotInfo;
+ screenshotInfo.fWidth = screenshot->getWidth();
+ screenshotInfo.fHeight = screenshot->getHeight();
- SkBitmap* bitmap = new SkBitmap();
- bitmap->setConfig(convertPixelFormat(f), w, h, bpr);
- if (f == PIXEL_FORMAT_RGBX_8888) {
- bitmap->setIsOpaque(true);
+ switch (screenshot->getFormat()) {
+ case PIXEL_FORMAT_RGBX_8888: {
+ screenshotInfo.fColorType = kRGBA_8888_SkColorType;
+ screenshotInfo.fAlphaType = kIgnore_SkAlphaType;
+ break;
+ }
+ case PIXEL_FORMAT_RGBA_8888: {
+ screenshotInfo.fColorType = kRGBA_8888_SkColorType;
+ screenshotInfo.fAlphaType = kPremul_SkAlphaType;
+ break;
+ }
+ case PIXEL_FORMAT_RGB_565: {
+ screenshotInfo.fColorType = kRGB_565_SkColorType;
+ screenshotInfo.fAlphaType = kIgnore_SkAlphaType;
+ break;
+ }
+ default: {
+ delete screenshot;
+ return NULL;
+ }
}
- if (w > 0 && h > 0) {
+ // takes ownership of ScreenshotClient
+ ScreenshotPixelRef* pixels = new ScreenshotPixelRef(screenshotInfo, screenshot);
+ ssize_t rowBytes = screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());
+
+ SkBitmap* bitmap = new SkBitmap();
+ bitmap->setConfig(screenshotInfo, rowBytes);
+ if (screenshotInfo.fWidth > 0 && screenshotInfo.fHeight > 0) {
bitmap->setPixelRef(pixels)->unref();
bitmap->lockPixels();
} else {
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index 0f429005..7a4a20a 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -27,6 +27,7 @@
#include <SkBitmap.h>
#include <SkCanvas.h>
+#include <SkImage.h>
namespace android {
@@ -156,7 +157,7 @@
bitmap.setConfig(convertPixelFormat(buffer.format), buffer.width, buffer.height, bytesCount);
if (buffer.format == WINDOW_FORMAT_RGBX_8888) {
- bitmap.setIsOpaque(true);
+ bitmap.setAlphaType(kOpaque_SkAlphaType);
}
if (buffer.width > 0 && buffer.height > 0) {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 69783bb..daff390 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1056,8 +1056,9 @@
android:permissionGroupFlags="personalInfo"
android:priority="370" />
- <!-- Allows an application to monitor, modify, or abort outgoing
- calls. -->
+ <!-- Allows an application to see the number being dialed during an outgoing
+ call with the option to redirect the call to a different number or
+ abort the call altogether. -->
<permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
android:permissionGroup="android.permission-group.PHONE_CALLS"
android:protectionLevel="dangerous"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 0358de3..dde6da0 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Tuis"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Werk"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Ander"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Geen program gekry om hierdie kontak te bekyk nie."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Voer PIN-kode in"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Voer PUK en nuwe PIN-kode in"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-kode"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index b649f5d..980465d 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -46,7 +46,7 @@
<string name="badPin" msgid="9015277645546710014">"የተየበከው የድሮ ፒን ትክክል አይደለም።"</string>
<string name="badPuk" msgid="5487257647081132201">"የተየብከው PUK ትክክል አይደለም።"</string>
<string name="mismatchPin" msgid="609379054496863419">"ያስገባሃቸው ፒኖች አይዛመዱም"</string>
- <string name="invalidPin" msgid="3850018445187475377">"ከ4 እስከ 8 ቁጥሮች የያዘ PIN ተይብ"</string>
+ <string name="invalidPin" msgid="3850018445187475377">"ከ4 እስከ 8 ቁጥሮች የያዘ ፒን ተይብ"</string>
<string name="invalidPuk" msgid="8761456210898036513">"8 ወይም ከዛ በላይ የሆኑ ቁጥሮችንPUK ተይብ።"</string>
<string name="needPuk" msgid="919668385956251611">"SIM ካርድዎ PUK-የተቆለፈ ነው።የPUK ኮዱን በመተየብ ይክፈቱት።"</string>
<string name="needPuk2" msgid="4526033371987193070">" SIM ለመክፈት PUK2 ተይብ።"</string>
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"መነሻ"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"ስራ"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"ሌላ"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"ምንም መተግበሪያ ይህንን እውቂያ ለመመልከት አልተገኘም።"</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"ፒን ኮድ ተይብ"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK እና አዲስ ፒን ተይብ"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"የPUK ኮድ"</string>
@@ -823,7 +824,7 @@
<string name="keyguard_password_entry_touch_hint" msgid="7858547464982981384"><font size="17">"የይለፍ ቃል ለመተየብ ንካ"</font></string>
<string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"ለመክፈት የይለፍ ቃል ተይብ"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"ለመክፈት ፒን ተይብ"</string>
- <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"ትክክል ያልሆነ PIN ኮድ።"</string>
+ <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"ትክክል ያልሆነ ፒን ኮድ።"</string>
<string name="keyguard_label_text" msgid="861796461028298424">"ለመክፈት፣ምናሌ ተጫን ከዛ 0"</string>
<string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"የአደጋ ጊዜቁጥር"</string>
<string name="lockscreen_carrier_default" msgid="8963839242565653192">"ከአገልግሎት መስጫ ክልል ውጪ"</string>
@@ -985,8 +986,8 @@
<string name="searchview_description_submit" msgid="2688450133297983542">"ጥያቄ አስረክብ"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"የድምፅ ፍለጋ"</string>
<string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"በመንካት አስስ ይንቃ?"</string>
- <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ማሰስን በንኪ ማንቃት ይፈልጋል። አስስ በንኪ በሚበራበት ጊዜ፣ ከጡባዊ ተኮው ጋር ለመግባባት ምን በጣትህ ስር ወይም ምልክቶችን ማከናወን እንዳለብህ ማብራሪያ ልታይ ወይም ልትሰማ ትችላለህ።"</string>
- <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ማሰስን በንኪ ማንቃት ይፈልጋል። አስስ በንኪ በሚበራበት ጊዜ፣ ከስልኩ ጋር ለመግባባት ምን በጣትህ ስር ወይም ምልክቶችን ማከናወን እንዳለብህ ማብራሪያ ልታይ ወይም ልትሰማ ትችላለህ።"</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ማሰስን በንኪ ማንቃት ይፈልጋል። አስስ በንኪ በሚበራበት ጊዜ፣ ከጡባዊ ተኮው ጋር ለመግባባት ምን በጣትዎ ስር ወይም ምልክቶችን ማከናወን እንዳለብዎ ማብራሪያ ሊመለከቱ ወይም ሊሰሙ ይችላሉ።"</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ማሰስን በንኪ ማንቃት ይፈልጋል። አስስ በንኪ በሚበራበት ጊዜ፣ ከስልኩ ጋር ለመግባባት ምን በጣትዎ ስር ወይም ምልክቶችን ማከናወን እንዳለብዎ ማብራሪያ ሊመለከቱ ወይም ሊሰሙ ይችላሉ።"</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"ከ1 ወር በፊት"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"ከ1 ወር በፊት"</string>
<plurals name="num_seconds_ago">
@@ -1232,7 +1233,7 @@
<string name="time_picker_dialog_title" msgid="8349362623068819295">"ጊዜ አዘጋጅ"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"ውሂብ አዘጋጅ"</string>
<string name="date_time_set" msgid="5777075614321087758">"አዘጋጅ"</string>
- <string name="date_time_done" msgid="2507683751759308828">"ተጠናቋል"</string>
+ <string name="date_time_done" msgid="2507683751759308828">"ተከናውኗል"</string>
<string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"አዲስ፦ "</font></string>
<string name="perms_description_app" msgid="5139836143293299417">"በ<xliff:g id="APP_NAME">%1$s</xliff:g> የቀረበ።"</string>
<string name="no_permissions" msgid="7283357728219338112">"ምንም ፍቃዶች አይጠየቁም"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 18296ea..2055c93 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"المنزل"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"العمل"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"غير ذلك"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"لم يتم العثور على تطبيق لعرض جهة الاتصال هذه."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"اكتب رمز رمز PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"اكتب رمز PUK ورمز رمز PIN الجديد"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"رمز PUK"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 0d1cdaf..0672cdf 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Домашен"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Служебен"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Друг"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Няма намерено приложение, с което да се отвори този контакт."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Въведете ПИН кода"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Въведете PUK и новия ПИН код"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK код"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index cf81367..b6c4762 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -675,8 +675,8 @@
<string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Permet que l\'aplicació modifiqui les marques de sòcols per a l\'encaminament"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"accedeix a les notificacions"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet que l\'aplicació recuperi, examini i esborri les notificacions, incloses les que han publicat altres aplicacions."</string>
- <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vincula a un servei de processament de notificacions"</string>
- <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet que el titular vinculi la interfície de nivell superior d\'un servei de processament de notificacions. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+ <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vincula a un servei oient de notificacions"</string>
+ <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet que el titular vinculi la interfície de nivell superior d\'un servei oient de notificacions. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invoca l\'aplicació de configuració proporcionada per l\'operador"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permet que el titular invoqui l\'aplicació de configuració proporcionada per l\'operador. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"conèixer les observacions sobre les condicions de la xarxa"</string>
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Casa"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Feina"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Altres"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"No hem trobat cap aplicació per mostrar aquest contacte."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Introdueix el codi PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Introdueix el codi PUK i el codi PIN nou"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Codi PUK"</string>
@@ -1335,7 +1336,7 @@
<string name="accessibility_binding_label" msgid="4148120742096474641">"Accessibilitat"</string>
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Fons de pantalla"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Canvia el fons de pantalla"</string>
- <string name="notification_listener_binding_label" msgid="2014162835481906429">"Processador de notificacions"</string>
+ <string name="notification_listener_binding_label" msgid="2014162835481906429">"Oient de notificacions"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ha activat VPN"</string>
<string name="vpn_text" msgid="3011306607126450322">"Toca per gestionar la xarxa."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 14d6dd5..da0dff4 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Domů"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Práce"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Jiné"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Nebyla nalezena žádná aplikace, pomocí které by tento kontakt bylo možné zobrazit."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Zadejte kód PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Zadejte kód PUK a nový kód PIN."</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Kód PUK"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 1d394a8..27e1cfb 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Hjem"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Arbejde"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Andet"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Der blev ikke fundet nogen applikation, som kan vise denne kontaktperson."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Indtast pinkode"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Indtast PUK- og pinkode"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-kode"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index dcd7671..d95bdca 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Privat"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Geschäftlich"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Sonstige"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Es wurde keine App zum Anzeigen dieses Kontakts gefunden."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN-Code eingeben"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK und neuen PIN-Code eingeben"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-Code"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index ee98ceb..482a9fa 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Αρχική σελίδα"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Εργασία"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Άλλο"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Δεν βρέθηκε καμία εφαρμογή για την προβολή αυτής της επαφής."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Πληκτρολογήστε τον κωδικό αριθμό PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Πληκτρολογήστε τον κωδικό PUK και τον νέο κωδικό PIN"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Κωδικός PUK"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index d2c53cc..a66eeda 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Home"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Work"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Other"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"No application found to view this contact."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Type PIN code"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Type PUK and new PIN code"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK code"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index d2c53cc..a66eeda 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Home"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Work"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Other"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"No application found to view this contact."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Type PIN code"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Type PUK and new PIN code"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK code"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 114f6f5..c7df6e6 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Casa"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Trabajo"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Otro"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"No se encontró ninguna aplicación para ver este contacto."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Ingresa el código PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Escribe el código PUK y un nuevo código PIN."</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Código PUK"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index f758989..95a623b 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Casa"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Trabajo"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Otro"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"No se ha encontrado ninguna aplicación para ver este contacto."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Introduce el código PIN."</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Introduce el código PUK y un nuevo código PIN."</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Código PUK"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 39523ef..1d24dea 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Kodu"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Töö"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Muu"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Selle kontakti kuvamiseks ei leitud ühtegi rakendust."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Sisestage PIN-kood"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Sisestage PUK-kood ja uus PIN-kood"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-kood"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 14836c2..18cc89d 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"صفحهٔ اصلی"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"محل کار"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"سایر موارد"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"هیچ برنامهای برای مشاهده این مخاطب پیدا نشد."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"پین کد را وارد کنید"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK و پین کد جدید را تایپ کنید"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"کد PUK"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index e4d4e3e..06e4fdd 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Koti"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Työ"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Muu"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Tämän kontaktin katselemiseen ei löydy sovellusta."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Anna PIN-koodi"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Anna PUK-koodi ja uusi PIN-koodi"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-koodi"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 2821897..b1a3f98 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Domicile"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Travail"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Autre"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Aucune application permettant d\'afficher ce contact n\'a été trouvée."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Saisissez le NIP."</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Saisissez la clé PUK et le nouveau NIP."</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Clé PUK"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 9944754..434b99b 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Domicile"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Professionnelle"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Autre"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Aucune application permettant d\'afficher ce contact n\'a été trouvée."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Saisissez le code PIN."</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Saisissez la clé PUK et le nouveau code PIN."</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Code PUK"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 2650108..925ee36 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"घर"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"कार्यालय"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"अन्य"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"इस संपर्क को देखने के लिए कोई एप्लिकेशन नहीं मिला."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"पिन कोड लिखें"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK और नया पिन कोड लिखें"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK कोड"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 829c03d..8e06edd 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -627,7 +627,7 @@
<string name="permlab_bluetooth" msgid="6127769336339276828">"uparivanje s Bluetooth uređajima"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Aplikaciji omogućuje pregled konfiguracije Bluetootha na tabletnom računalu te uspostavljanje i prihvaćanje veza s uparenim uređajima."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Aplikaciji omogućuje pregled konfiguracije Bluetootha na telefonu te uspostavljanje i prihvaćanje veza s uparenim uređajima."</string>
- <string name="permlab_nfc" msgid="4423351274757876953">"upravljaj beskontaktnom (NFC) komunikacijom"</string>
+ <string name="permlab_nfc" msgid="4423351274757876953">"upravljanje beskontaktnom komunikacijom (NFC)"</string>
<string name="permdesc_nfc" msgid="7120611819401789907">"Aplikaciji omogućuje komunikaciju s oznakama, karticama i čitačima komunikacije kratkog dometa (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"onemogućavanje zaključavanja zaslona"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Aplikaciji omogućuje onemogućavanje zaključavanja tipkovnice i svih pripadajućih sigurnosnih zaporki. Na primjer, telefon onemogućuje zaključavanje tipkovnice kod primanja dolaznog telefonskog poziva, nakon kojeg se zaključavanje tipkovnice ponovo omogućuje."</string>
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Početna"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Posao"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Drugo"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Nema aplikacije za prikazivanje tog kontakta."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Unesite PIN kôd"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Unesite PUK i novi PIN kôd"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK kôd"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 5ed894e..005dcbe 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Otthoni"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Munkahely"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Egyéb"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Nem található alkalmazás a névjegy megtekintéshez."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Írja be a PIN kódot"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Írja be a PUK kódot, majd az új PIN kódot"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK kód"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 85eedba..5789e5f 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Տնային"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Աշխատանքային"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Այլ"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Այս կոնտակտը դիտելու համար համապատասխան ծրագիր չկա:"</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Մուտքագրեք PIN կոդը"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Մուտքագրեք PUK-ը և նոր PIN կոդը"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK կոդ"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 633621a..7acc02b 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Beranda"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Kerjaan"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Lainnya"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Tidak ada aplikasi yang ditemukan untuk melihat kontak ini."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Ketik kode PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Ketik kode PUK dan PIN baru"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Kode PUK"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 6bae95b..fdee440 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Casa"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Lavoro"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Altro"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Nessuna applicazione trovata per la visualizzazione di questo contatto."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Inserisci il codice PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Inserisci il PUK e il nuovo codice PIN"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Codice PUK"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 3d82fef..b3f5439 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"דף הבית"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"עבודה"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"אחר"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"לא נמצאה אפליקציה להצגת התוכן הזה."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"הקלד קוד PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"הקלד את קוד ה-PUK וקוד ה-PIN החדש"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"קוד PUK"</string>
diff --git a/core/res/res/values-ja/bools.xml b/core/res/res/values-ja/bools.xml
deleted file mode 100644
index 59cf744..0000000
--- a/core/res/res/values-ja/bools.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources>
- <bool name="flip_controller_fallback_keys">true</bool>
-</resources>
-
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 559d53f..b7ccb6a 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"自宅"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"勤務先"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"その他"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"この連絡先を表示するアプリが見つかりません。"</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PINコードを入力"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUKと新しいPINコードを入力"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUKコード"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 7f4dc90..ea36ab0 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"სახლი"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"სამსახური"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"სხვა"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"ამ კონტაქტის მნახველი აპლიკაცია ვერ მოიძებნა."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"აკრიფეთ PIN კოდი"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"დაბეჭდეთ PUK კოდი და ახალი PIN კოდი."</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK კოდი"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index f03b5ed..f12b003 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"គេហទំព័រ"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"កន្លែងធ្វើការ"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"ផ្សេងៗ"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"រកមិនឃើញកម្មវិធី ដើម្បីមើលទំនាក់ទំនងនេះទេ។"</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"បញ្ចូលកូដ PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"បញ្ចូលកូដ PUK និង PIN ថ្មី"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"កូដ PUK"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index cbfb1db..18c15a9 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"집"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"직장"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"기타"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"이 주소록을 표시할 수 있는 애플리케이션이 없습니다."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN 코드 입력"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK 및 새 PIN 코드 입력"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK 코드"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 8d88dfee9f..cd0d471 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"ເຮືອນ"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"ບ່ອນເຮັດວຽກ"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"ອື່ນໆ"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"ບໍ່ພົບແອັບຯທີ່ຕິດຕໍ່ນີ້."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"ພິມລະຫັດ PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"ພິມລະຫັດ PUK ແລະລະຫັດ PIN ອັນໃໝ່"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"ລະຫັດ PUK"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 614bcd6..d11051f 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Pagrindinis"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Darbas"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Kita"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Nerasta jokių programų šiam kontaktui peržiūrėti."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Įveskite PIN kodą"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Įveskite PUK ir naują PIN kodus"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK kodas"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 9f3cb53..022917a 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Mājās"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Darbs"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Cits"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Netika atrasta neviena lietojumprogramma, ar kuru skatīt šo kontaktpersonu."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Ievadiet PIN kodu."</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Ievadiet PUK kodu un jaunu PIN kodu."</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK kods"</string>
diff --git a/core/res/res/values-mcc302-mnc500/config.xml b/core/res/res/values-mcc302-mnc500/config.xml
deleted file mode 100644
index 706570c..0000000
--- a/core/res/res/values-mcc302-mnc500/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2013, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Don't use roaming icon for considered operators -->
- <string-array translatable="false" name="config_operatorConsideredNonRoaming">
- <item>302</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-mcc302-mnc510/config.xml b/core/res/res/values-mcc302-mnc510/config.xml
deleted file mode 100644
index 706570c..0000000
--- a/core/res/res/values-mcc302-mnc510/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2013, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Don't use roaming icon for considered operators -->
- <string-array translatable="false" name="config_operatorConsideredNonRoaming">
- <item>302</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-mcc404-mnc17/config.xml b/core/res/res/values-mcc404-mnc17/config.xml
deleted file mode 100644
index 685d012..0000000
--- a/core/res/res/values-mcc404-mnc17/config.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2013, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Show roaming icon though same named operators. -->
- <string-array translatable="false" name="config_sameNamedOperatorConsideredRoaming">
- <item>40491</item>
- </string-array>
-</resources>
diff --git a/core/res/res/values-mcc404-mnc85/config.xml b/core/res/res/values-mcc404/config.xml
similarity index 94%
copy from core/res/res/values-mcc404-mnc85/config.xml
copy to core/res/res/values-mcc404/config.xml
index fd780ab..a106b0a 100644
--- a/core/res/res/values-mcc404-mnc85/config.xml
+++ b/core/res/res/values-mcc404/config.xml
@@ -20,6 +20,7 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Show roaming icon though same named operators. -->
<string-array translatable="false" name="config_sameNamedOperatorConsideredRoaming">
- <item>40483</item>
+ <item>404</item>
+ <item>405</item>
</string-array>
</resources>
diff --git a/core/res/res/values-mcc404-mnc85/config.xml b/core/res/res/values-mcc405/config.xml
similarity index 94%
copy from core/res/res/values-mcc404-mnc85/config.xml
copy to core/res/res/values-mcc405/config.xml
index fd780ab..a106b0a 100644
--- a/core/res/res/values-mcc404-mnc85/config.xml
+++ b/core/res/res/values-mcc405/config.xml
@@ -20,6 +20,7 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Show roaming icon though same named operators. -->
<string-array translatable="false" name="config_sameNamedOperatorConsideredRoaming">
- <item>40483</item>
+ <item>404</item>
+ <item>405</item>
</string-array>
</resources>
diff --git a/core/res/res/values-mcc404-mnc85/config.xml b/core/res/res/values-mcc520/config.xml
similarity index 96%
rename from core/res/res/values-mcc404-mnc85/config.xml
rename to core/res/res/values-mcc520/config.xml
index fd780ab..b2f3efa 100644
--- a/core/res/res/values-mcc404-mnc85/config.xml
+++ b/core/res/res/values-mcc520/config.xml
@@ -20,6 +20,6 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Show roaming icon though same named operators. -->
<string-array translatable="false" name="config_sameNamedOperatorConsideredRoaming">
- <item>40483</item>
+ <item>520</item>
</string-array>
</resources>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 252a959..c58184d 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Гэрийн"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Ажлын"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Бусад"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Энэ харилцагчийг харах аппликешн олдсонгүй."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN кодыг бичнэ үү"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK-г бичээд шинэ PIN код оруулна уу"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK код"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 284837a..2f5769e 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Rumah"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Kerja"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Lain-lain"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Tiada aplikasi ditemui untuk melihat kenalan ini."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Taip kod PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Taip PUK dan kod PIN baharu"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Kod PUK"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 122bf1a..ff17815 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Hjem"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Arbeid"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Annen"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Du har ingen apper som kan åpne denne kontakten."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Skriv inn PIN-kode"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Skriv inn PUK-kode og ny personlig kode"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-kode"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index ba5ac11..27d6836 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Startpagina"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Werk"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Overig"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Er is geen app gevonden om dit contact te bekijken."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Pincode typen"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Geef de PUK-code en de nieuwe pincode op"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-code"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 7e9a8c4..b8c20f5 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Domowy"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Służbowy"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Inny"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Brak aplikacji do wyświetlenia tego kontaktu."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Wpisz kod PIN."</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Wpisz kod PUK i nowy kod PIN."</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Kod PUK"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 2d69f9c..6fff221 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Casa"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Emprego"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Outro"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Não foram encontradas aplicações para visualizar este contacto."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Escreva o código PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Escreva o PUK e o novo código PIN"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Código PUK"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index f1ad4d7..b6e8fbc 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Página inicial"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Comercial"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Outros"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Nenhum aplicativo encontrado para visualizar este contato."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Insira o código PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Insira o PUK e o novo código PIN"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Código PUK"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 6ea1e9e..45e6951 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -1330,6 +1330,8 @@
<skip />
<!-- no translation found for sipAddressTypeOther (4408436162950119849) -->
<skip />
+ <!-- no translation found for quick_contacts_not_available (746098007828579688) -->
+ <skip />
<!-- no translation found for keyguard_password_enter_pin_code (3037685796058495017) -->
<skip />
<!-- no translation found for keyguard_password_enter_puk_code (4800725266925845333) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index c3f9157..fcd5809 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Ecran pornire"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Serviciu"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Altul"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Nu s-a găsit nicio aplicație pentru a afișa această persoană de contact."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Introduceţi codul PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Introduceţi codul PUK şi noul cod PIN"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Codul PUK"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index b853e8d..0eab8e8 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Домашний"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Рабочий"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Другой"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Не найдено приложение для просмотра контакта"</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Введите PIN-код"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Введите PUK-код и новый PIN-код"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-код"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index d19d87a..30320b2 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -190,7 +190,7 @@
<string name="permgroupdesc_bluetoothNetwork" msgid="5625288577164282391">"Prístup k zariadeniam a sieťam prostredníctvom rozhrania Bluetooth."</string>
<string name="permgrouplab_audioSettings" msgid="8329261670151871235">"Nastavenia zvuku"</string>
<string name="permgroupdesc_audioSettings" msgid="2641515403347568130">"Zmena nastavení zvuku."</string>
- <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Má vplyv na batériu"</string>
+ <string name="permgrouplab_affectsBattery" msgid="6209246653424798033">"Vplyv na batériu"</string>
<string name="permgroupdesc_affectsBattery" msgid="6441275320638916947">"Používanie funkcií, ktoré môžu rýchlo vyčerpať batériu."</string>
<string name="permgrouplab_calendar" msgid="5863508437783683902">"Kalendár"</string>
<string name="permgroupdesc_calendar" msgid="5777534316982184416">"Priamy prístup ku kalendáru a udalostiam."</string>
@@ -232,7 +232,7 @@
<string name="permgroupdesc_developmentTools" msgid="7058828032358142018">"Funkcie len pre vývojárov aplikácií."</string>
<string name="permgrouplab_display" msgid="4279909676036402636">"Používateľské rozhranie iných aplikácií"</string>
<string name="permgroupdesc_display" msgid="6051002031933013714">"Vplyv na používateľské rozhranie ďalších aplikácií."</string>
- <string name="permgrouplab_storage" msgid="1971118770546336966">"Ukladací priestor"</string>
+ <string name="permgrouplab_storage" msgid="1971118770546336966">"Úložisko"</string>
<string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Prístup do ukl. priestoru USB."</string>
<string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Prístup na kartu SD."</string>
<string name="permgrouplab_accessibilityFeatures" msgid="7919025602283593907">"Funkcie zjednodušenia ovládania"</string>
@@ -558,7 +558,7 @@
<string name="permlab_readPhoneState" msgid="9178228524507610486">"čítať stav a identitu telefónu"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Umožňuje aplikácii pristupovať k telefónnym funkciám zariadenia. Aplikácia s týmto povolením môže určiť telefónne číslo a ID zariadenia, či práve prebieha hovor, a vzdialené číslo, s ktorým je prostredníctvom hovoru nadviazané spojenie."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zabránenie prechodu tabletu do režimu spánku"</string>
- <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"zabránenie prechodu telefónu do režimu spánku"</string>
+ <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"deaktivácia režimu spánku"</string>
<string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Umožňuje aplikácii zabrániť prechodu tabletu do režimu spánku."</string>
<string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"Umožňuje aplikácii zabrániť prechodu telefónu do režimu spánku."</string>
<string name="permlab_transmitIr" msgid="7545858504238530105">"infračervený prenos"</string>
@@ -629,7 +629,7 @@
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Umožňuje aplikácii zobraziť informácie o konfigurácii Bluetooth na telefóne. Taktiež jej umožňuje nadväzovať a akceptovať spojenia so spárovanými zariadeniami."</string>
<string name="permlab_nfc" msgid="4423351274757876953">"ovládať technológiu Near Field Communication"</string>
<string name="permdesc_nfc" msgid="7120611819401789907">"Umožňuje aplikácii komunikovať so značkami, kartami a čítačkami s podporou technológie Near Field Communication (NFC)."</string>
- <string name="permlab_disableKeyguard" msgid="3598496301486439258">"zakázať uzamknutie obrazovky"</string>
+ <string name="permlab_disableKeyguard" msgid="3598496301486439258">"deaktivácia zámky obrazovky"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Umožňuje aplikácii zakázať uzamknutie klávesnice a akékoľvek súvisiace zabezpečenie heslom. Príkladom je zakázanie uzamknutia klávesnice pri prichádzajúcom telefonickom hovore a jeho opätovné povolenie po skončení hovoru."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"čítanie nastavení synchronizácie"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Umožňuje aplikácii čítať nastavenia synchronizácie v účte. Môže napríklad určiť, či je s účtom synchronizovaná aplikácia Ľudia."</string>
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Domov"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Práca"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Iné"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Nebola nájdená žiadna aplikácia, pomocou ktorej by bolo možné zobraziť tento kontakt."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Zadajte kód PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Zadajte kód PUK a nový kód PIN"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Kód PUK"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 0d76bbf..8972edf 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Domov"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Služba"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Drugo"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Ni aplikacije za ogled tega stika."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Vnesite kodo PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Vnesite kodo PUK in novo kodo PIN"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Koda PUK"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 6fb9ea2..b9c7beb 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Почетна"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Посао"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Други"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Није пронађена ниједна апликација за приказ овог контакта."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Унесите PIN кôд"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Унесите PUK и нови PIN кôд"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK кôд"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 7123012..eb5e900 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Hem"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Arbete"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Övrigt"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Ingen app för att visa den här kontakten hittades."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Ange PIN-kod"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Ange PUK-koden och en ny PIN-kod"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-kod"</string>
@@ -1459,7 +1460,7 @@
<string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Gränsen för data via Wi-Fi har överskridits"</string>
<string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> över angiven gräns."</string>
<string name="data_usage_restricted_title" msgid="5965157361036321914">"Bakgrundsdata är begränsade"</string>
- <string name="data_usage_restricted_body" msgid="6741521330997452990">"Tryck för att radera begränsning"</string>
+ <string name="data_usage_restricted_body" msgid="6741521330997452990">"Tryck för att ta bort begränsning"</string>
<string name="ssl_certificate" msgid="6510040486049237639">"Säkerhetscertifikat"</string>
<string name="ssl_certificate_is_valid" msgid="6825263250774569373">"Certifikatet är giltigt."</string>
<string name="issued_to" msgid="454239480274921032">"Utfärdad till:"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index c268476..c5f3f90 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Nyumbani"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Kazi"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Nyinginezo"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Hakuna programu iliyopatikana ili kuona anwani hii."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Ingiza msimbo wa PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Ingiza PUK na msimbo mpya wa PIN"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Msimbo wa PUK"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index f298a8f..34c70e2 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"หน้าแรก"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"ที่ทำงาน"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"อื่นๆ"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"ไม่พบแอปพลิเคชันที่ใช้ดูที่อยู่ติดต่อนี้"</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"พิมพ์รหัส PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"พิมพ์ PUK และรหัส PIN ใหม่"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"รหัส PUK"</string>
@@ -1352,7 +1353,7 @@
<string name="car_mode_disable_notification_message" msgid="8035230537563503262">"แตะเพื่อออกจากโหมดรถยนต์"</string>
<string name="tethered_notification_title" msgid="3146694234398202601">"การปล่อยสัญญาณหรือฮอตสปอตทำงานอยู่"</string>
<string name="tethered_notification_message" msgid="6857031760103062982">"แตะเพื่อตั้งค่า"</string>
- <string name="back_button_label" msgid="2300470004503343439">"ย้อนกลับ"</string>
+ <string name="back_button_label" msgid="2300470004503343439">"กลับ"</string>
<string name="next_button_label" msgid="1080555104677992408">"ถัดไป"</string>
<string name="skip_button_label" msgid="1275362299471631819">"ข้าม"</string>
<string name="throttle_warning_notification_title" msgid="4890894267454867276">"การใช้งานข้อมูลมือถือในระดับสูง"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 85dd968..18d4759 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Home"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Trabaho"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Iba pa"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Walang nakitang application upang matingnan ang contact na ito."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"I-type ang PIN code"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"I-type ang PUK at bagong PIN code"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK code"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 9ca752e..6c0e81f 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Ev"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"İş"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Diğer"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Bu kişiyi görüntüleyecek uygulama bulunamadı."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN kodunu yazın"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"PUK ve yeni PIN kodunu yazın"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK kodu"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 556b35b..3bfecc3 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Головна"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Робоча"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Інша"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Не знайдено програму для перегляду цього контакта."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Введіть PIN-код"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Введіть PUK-код і новий PIN-код"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK-код"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index c8f5014..cfcc02e 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Nhà riêng"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Cơ quan"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Khác"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Không tìm thấy ứng dụng nào để xem liên hệ này."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Nhập mã PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Nhập PUK và mã PIN mới"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Mã PUK"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index f65950e..adf2d4b 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -76,7 +76,7 @@
<string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"默认显示本机号码,在下一次通话中也显示"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"未提供服务。"</string>
<string name="CLIRPermanent" msgid="3377371145926835671">"您无法更改来电显示设置。"</string>
- <string name="RestrictedChangedTitle" msgid="5592189398956187498">"访问受限情况已发生变化"</string>
+ <string name="RestrictedChangedTitle" msgid="5592189398956187498">"网络可用情况发生变化"</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"数据服务已禁用。"</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"紧急服务已禁用。"</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"已禁用语音服务。"</string>
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"住宅"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"单位"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"其他"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"找不到可用来查看此联系人的应用。"</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"输入 PIN 码"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"请输入 PUK 码和新的 PIN 码"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK 码"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index ab8ceed..f954c24 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"家用"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"工作"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"其他"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"找不到可以查看這位聯絡人的應用程式。"</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"輸入 PIN 碼"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"輸入 PUK 碼和新 PIN 碼"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK 碼"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 40d6260..5eeea00 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"住家"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"公司"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"其他"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"找不到可用來查看這位聯絡人的應用程式。"</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"輸入 PIN 碼"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"輸入 PUK 碼和新 PIN 碼"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK 碼"</string>
@@ -1129,7 +1130,7 @@
<string name="chooseUsbActivity" msgid="6894748416073583509">"選取要以 USB 裝置存取的應用程式"</string>
<string name="noApplications" msgid="2991814273936504689">"沒有應用程式可執行這項操作。"</string>
<string name="aerr_title" msgid="1905800560317137752"></string>
- <string name="aerr_application" msgid="932628488013092776">"很抱歉,<xliff:g id="APPLICATION">%1$s</xliff:g> 已停止。"</string>
+ <string name="aerr_application" msgid="932628488013092776">"很抱歉,<xliff:g id="APPLICATION">%1$s</xliff:g>已停止運作。"</string>
<string name="aerr_process" msgid="4507058997035697579">"很抱歉,處理程序 <xliff:g id="PROCESS">%1$s</xliff:g> 已停止。"</string>
<string name="anr_title" msgid="4351948481459135709"></string>
<string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> 沒有回應。\n\n您要結束嗎?"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 563cb3f..0583640 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -816,6 +816,7 @@
<string name="sipAddressTypeHome" msgid="6093598181069359295">"Ekhaya"</string>
<string name="sipAddressTypeWork" msgid="6920725730797099047">"Umsebenzi"</string>
<string name="sipAddressTypeOther" msgid="4408436162950119849">"Okunye"</string>
+ <string name="quick_contacts_not_available" msgid="746098007828579688">"Alukho uhlelo lokusebenza olutholakele lokubuka lona oxhumana naye."</string>
<string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Faka ikhodi ye-PIN"</string>
<string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Faka i-PUK nephinikhodi entsha"</string>
<string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"Ikhodi le-PUK"</string>
diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml
index 10a5d85..18e4f2f 100644
--- a/core/res/res/values/bools.xml
+++ b/core/res/res/values/bools.xml
@@ -26,5 +26,4 @@
<bool name="show_ongoing_ime_switcher">true</bool>
<bool name="action_bar_expanded_action_views_exclusive">true</bool>
<bool name="target_honeycomb_needs_options_menu">true</bool>
- <bool name="flip_controller_fallback_keys">false</bool>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4940f80..098fbbe 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -625,9 +625,9 @@
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_processOutgoingCalls">reroute outgoing calls</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permdesc_processOutgoingCalls">Allows the app to process
- outgoing calls and change the number to be dialed. This permission allows
- the app to monitor, redirect, or prevent outgoing calls.</string>
+ <string name="permdesc_processOutgoingCalls">Allows the app to see the
+ number being dialed during an outgoing call with the option to redirect
+ the call to a different number or abort the call altogether.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_receiveSms">receive text messages (SMS)</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index bface57..b635039 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -288,7 +288,6 @@
<java-symbol type="bool" name="config_useFixedVolume" />
<java-symbol type="bool" name="config_forceDefaultOrientation" />
<java-symbol type="bool" name="config_wifi_batched_scan_supported" />
- <java-symbol type="bool" name="flip_controller_fallback_keys" />
<java-symbol type="integer" name="config_cursorWindowSize" />
<java-symbol type="integer" name="config_extraFreeKbytesAdjust" />
diff --git a/data/keyboards/AVRCP.kl b/data/keyboards/AVRCP.kl
index 4c91ece..736b43c 100644
--- a/data/keyboards/AVRCP.kl
+++ b/data/keyboards/AVRCP.kl
@@ -14,8 +14,8 @@
# Key layout used for Bluetooth AVRCP support.
-key 200 MEDIA_PLAY_PAUSE WAKE
-key 201 MEDIA_PLAY_PAUSE WAKE
+key 200 MEDIA_PLAY WAKE
+key 201 MEDIA_PAUSE WAKE
key 166 MEDIA_STOP WAKE
key 163 MEDIA_NEXT WAKE
key 165 MEDIA_PREVIOUS WAKE
diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm
index 695a74f..01d22ee 100644
--- a/data/keyboards/Generic.kcm
+++ b/data/keyboards/Generic.kcm
@@ -477,4 +477,128 @@
ctrl: fallback MENU
}
-### Gamepad buttons are handled by the view root ###
+### Gamepad buttons ###
+
+key BUTTON_A {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_B {
+ base: fallback BACK
+}
+
+key BUTTON_C {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_X {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_Y {
+ base: fallback BACK
+}
+
+key BUTTON_Z {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_L1 {
+ base: none
+}
+
+key BUTTON_R1 {
+ base: none
+}
+
+key BUTTON_L2 {
+ base: none
+}
+
+key BUTTON_R2 {
+ base: none
+}
+
+key BUTTON_THUMBL {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_THUMBR {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_START {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_SELECT {
+ base: fallback MENU
+}
+
+key BUTTON_MODE {
+ base: fallback MENU
+}
+
+key BUTTON_1 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_2 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_3 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_4 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_5 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_6 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_7 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_8 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_9 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_10 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_11 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_12 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_13 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_14 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_15 {
+ base: fallback DPAD_CENTER
+}
+
+key BUTTON_16 {
+ base: fallback DPAD_CENTER
+}
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 8c38d25..17727d3 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -67,6 +67,16 @@
* setPremultiplied() aren't order dependent, despite being setters.
*/
private boolean mIsPremultiplied;
+
+ /**
+ * Whether the Bitmap's content is expected to have alpha. Note that hasAlpha()
+ * does not directly return this value, because hasAlpha() may never return true
+ * for a 565 Bitmap.
+ *
+ * Any time this or mIsPremultiplied is changed, both are passed to native so they
+ * are not order dependent.
+ */
+ private boolean mHasAlpha;
private byte[] mNinePatchChunk; // may be null
private int[] mLayoutBounds; // may be null
private int mWidth;
@@ -390,7 +400,7 @@
* No color information is stored.
* With this configuration, each pixel requires 1 byte of memory.
*/
- ALPHA_8 (2),
+ ALPHA_8 (1),
/**
* Each pixel is stored on 2 bytes and only the RGB channels are
@@ -406,7 +416,7 @@
* This configuration may be useful when using opaque bitmaps
* that do not require high color fidelity.
*/
- RGB_565 (4),
+ RGB_565 (3),
/**
* Each pixel is stored on 2 bytes. The three RGB color channels
@@ -428,7 +438,7 @@
* it is advised to use {@link #ARGB_8888} instead.
*/
@Deprecated
- ARGB_4444 (5),
+ ARGB_4444 (4),
/**
* Each pixel is stored on 4 bytes. Each channel (RGB and alpha
@@ -438,13 +448,13 @@
* This configuration is very flexible and offers the best
* quality. It should be used whenever possible.
*/
- ARGB_8888 (6);
+ ARGB_8888 (5);
final int nativeInt;
@SuppressWarnings({"deprecation"})
private static Config sConfigs[] = {
- null, null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888
+ null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888
};
Config(int ni) {
@@ -554,7 +564,7 @@
checkRecycled("Can't copy a recycled bitmap");
Bitmap b = nativeCopy(mNativeBitmap, config.nativeInt, isMutable);
if (b != null) {
- b.mIsPremultiplied = mIsPremultiplied;
+ b.setAlphaAndPremultiplied(mHasAlpha, mIsPremultiplied);
b.mDensity = mDensity;
}
return b;
@@ -727,12 +737,12 @@
paint.setAntiAlias(true);
}
}
-
+
// The new bitmap was created from a known bitmap source so assume that
// they use the same density
bitmap.mDensity = source.mDensity;
- bitmap.mIsPremultiplied = source.mIsPremultiplied;
-
+ bitmap.setAlphaAndPremultiplied(source.mHasAlpha, source.mIsPremultiplied);
+
canvas.setBitmap(bitmap);
canvas.drawBitmap(source, srcR, dstR, paint);
canvas.setBitmap(null);
@@ -810,9 +820,9 @@
if (display != null) {
bm.mDensity = display.densityDpi;
}
+ bm.setHasAlpha(hasAlpha);
if (config == Config.ARGB_8888 && !hasAlpha) {
nativeErase(bm.mNativeBitmap, 0xff000000);
- nativeSetHasAlpha(bm.mNativeBitmap, hasAlpha);
}
// No need to initialize the bitmap to zeroes with other configs;
// it is backed by a VM byte array which is by definition preinitialized
@@ -884,6 +894,7 @@
if (display != null) {
bm.mDensity = display.densityDpi;
}
+ bm.mHasAlpha = true;
return bm;
}
@@ -1041,11 +1052,24 @@
* <p>This method will not affect the behavior of a bitmap without an alpha
* channel, or if {@link #hasAlpha()} returns false.</p>
*
+ * <p>Calling createBitmap() or createScaledBitmap() with a source
+ * Bitmap whose colors are not pre-multiplied may result in a RuntimeException,
+ * since those functions require drawing the source, which is not supported for
+ * un-pre-multiplied Bitmaps.</p>
+ *
* @see Bitmap#isPremultiplied()
* @see BitmapFactory.Options#inPremultiplied
*/
public final void setPremultiplied(boolean premultiplied) {
mIsPremultiplied = premultiplied;
+ nativeSetAlphaAndPremultiplied(mNativeBitmap, mHasAlpha, premultiplied);
+ }
+
+ /** Helper function to set both alpha and premultiplied. **/
+ private final void setAlphaAndPremultiplied(boolean hasAlpha, boolean premultiplied) {
+ mHasAlpha = hasAlpha;
+ mIsPremultiplied = premultiplied;
+ nativeSetAlphaAndPremultiplied(mNativeBitmap, hasAlpha, premultiplied);
}
/** Returns the bitmap's width */
@@ -1206,7 +1230,8 @@
* non-opaque per-pixel alpha values.
*/
public void setHasAlpha(boolean hasAlpha) {
- nativeSetHasAlpha(mNativeBitmap, hasAlpha);
+ mHasAlpha = hasAlpha;
+ nativeSetAlphaAndPremultiplied(mNativeBitmap, hasAlpha, mIsPremultiplied);
}
/**
@@ -1611,7 +1636,8 @@
private static native void nativePrepareToDraw(int nativeBitmap);
private static native boolean nativeHasAlpha(int nativeBitmap);
- private static native void nativeSetHasAlpha(int nBitmap, boolean hasAlpha);
+ private static native void nativeSetAlphaAndPremultiplied(int nBitmap, boolean hasAlpha,
+ boolean isPremul);
private static native boolean nativeHasMipMap(int nativeBitmap);
private static native void nativeSetHasMipMap(int nBitmap, boolean hasMipMap);
private static native boolean nativeSameAs(int nb0, int nb1);
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index b08ce09..9b07da9 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -153,8 +153,12 @@
*
* <p>This does not affect bitmaps without an alpha channel.</p>
*
+ * <p>Setting this flag to false while setting {@link #inScaled} to true
+ * may result in incorrect colors.</p>
+ *
* @see Bitmap#hasAlpha()
* @see Bitmap#isPremultiplied()
+ * @see #inScaled
*/
public boolean inPremultiplied;
@@ -249,6 +253,9 @@
* <p>This flag is turned on by default and should be turned off if you need
* a non-scaled version of the bitmap. Nine-patch bitmaps ignore this
* flag and are always scaled.
+ *
+ * <p>If {@link #inPremultiplied} is set to false, and the image has alpha,
+ * setting this flag to true may result in incorrect colors.
*/
public boolean inScaled;
diff --git a/graphics/java/android/renderscript/AllocationAdapter.java b/graphics/java/android/renderscript/AllocationAdapter.java
index a6645bb..84a9ad3 100644
--- a/graphics/java/android/renderscript/AllocationAdapter.java
+++ b/graphics/java/android/renderscript/AllocationAdapter.java
@@ -224,7 +224,6 @@
}
static public AllocationAdapter create2D(RenderScript rs, Allocation a) {
- android.util.Log.e("rs", "create2d " + a);
rs.validate();
AllocationAdapter aa = new AllocationAdapter(0, rs, a);
aa.mConstrainedLOD = true;
diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java
index e17d79a..fc54532 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/graphics/java/android/renderscript/BaseObj.java
@@ -16,7 +16,7 @@
package android.renderscript;
-import android.util.Log;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* BaseObj is the base class for all RenderScript objects owned by a RS context.
@@ -109,17 +109,31 @@
return mName;
}
- protected void finalize() throws Throwable {
- if (!mDestroyed) {
- if(mID != 0 && mRS.isAlive()) {
+ private void helpDestroy() {
+ boolean shouldDestroy = false;
+ synchronized(this) {
+ if (!mDestroyed) {
+ shouldDestroy = true;
+ mDestroyed = true;
+ }
+ }
+
+ if (shouldDestroy) {
+ // must include nObjDestroy in the critical section
+ ReentrantReadWriteLock.ReadLock rlock = mRS.mRWLock.readLock();
+ rlock.lock();
+ // AllocationAdapters are BaseObjs with an ID of 0 but should not be passed to nObjDestroy
+ if(mRS.isAlive() && mID != 0) {
mRS.nObjDestroy(mID);
}
+ rlock.unlock();
mRS = null;
mID = 0;
- mDestroyed = true;
- //Log.v(RenderScript.LOG_TAG, getClass() +
- // " auto finalizing object without having released the RS reference.");
}
+ }
+
+ protected void finalize() throws Throwable {
+ helpDestroy();
super.finalize();
}
@@ -128,12 +142,11 @@
* primary use is to force immediate cleanup of resources when it is
* believed the GC will not respond quickly enough.
*/
- synchronized public void destroy() {
+ public void destroy() {
if(mDestroyed) {
throw new RSInvalidStateException("Object already destroyed.");
}
- mDestroyed = true;
- mRS.nObjDestroy(mID);
+ helpDestroy();
}
/**
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 7d4a5c4..35fe8c4 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -19,6 +19,7 @@
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -102,6 +103,20 @@
static File mCacheDir;
+ // this should be a monotonically increasing ID
+ // used in conjunction with the API version of a device
+ static final long sMinorID = 1;
+
+ /**
+ * Returns an identifier that can be used to identify a particular
+ * minor version of RS.
+ *
+ * @hide
+ */
+ public static long getMinorID() {
+ return sMinorID;
+ }
+
/**
* Sets the directory to use as a persistent storage for the
* renderscript object file cache.
@@ -151,6 +166,7 @@
}
ContextType mContextType;
+ ReentrantReadWriteLock mRWLock;
// Methods below are wrapped to protect the non-threadsafe
// lockless fifo.
@@ -178,7 +194,18 @@
native void rsnContextDestroy(int con);
synchronized void nContextDestroy() {
validate();
- rsnContextDestroy(mContext);
+
+ // take teardown lock
+ // teardown lock can only be taken when no objects are being destroyed
+ ReentrantReadWriteLock.WriteLock wlock = mRWLock.writeLock();
+ wlock.lock();
+
+ int curCon = mContext;
+ // context is considered dead as of this point
+ mContext = 0;
+
+ wlock.unlock();
+ rsnContextDestroy(curCon);
}
native void rsnContextSetSurface(int con, int w, int h, Surface sur);
synchronized void nContextSetSurface(int w, int h, Surface sur) {
@@ -263,8 +290,9 @@
validate();
return rsnGetName(mContext, obj);
}
+ // nObjDestroy is explicitly _not_ synchronous to prevent crashes in finalizers
native void rsnObjDestroy(int con, int id);
- synchronized void nObjDestroy(int id) {
+ void nObjDestroy(int id) {
// There is a race condition here. The calling code may be run
// by the gc while teardown is occuring. This protects againts
// deleting dead objects.
@@ -1136,6 +1164,7 @@
if (ctx != null) {
mApplicationContext = ctx.getApplicationContext();
}
+ mRWLock = new ReentrantReadWriteLock();
}
/**
@@ -1230,6 +1259,8 @@
*/
public void destroy() {
validate();
+ nContextFinish();
+
nContextDeinitToClient(mContext);
mMessageThread.mRun = false;
try {
@@ -1238,7 +1269,6 @@
}
nContextDestroy();
- mContext = 0;
nDeviceDestroy(mDev);
mDev = 0;
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index ed0a79a..8d0874f 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -285,10 +285,9 @@
void TextureCache::uploadLoFiTexture(bool resize, SkBitmap* bitmap,
uint32_t width, uint32_t height) {
SkBitmap rgbaBitmap;
- rgbaBitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
+ rgbaBitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height, 0, bitmap->alphaType());
rgbaBitmap.allocPixels();
rgbaBitmap.eraseColor(0);
- rgbaBitmap.setIsOpaque(bitmap->isOpaque());
SkCanvas canvas(rgbaBitmap);
canvas.drawBitmap(*bitmap, 0.0f, 0.0f, NULL);
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index 18983d8..12a9c23 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -23,6 +23,7 @@
#include <utils/Trace.h>
#include <SkGlyph.h>
+#include <SkGlyphCache.h>
#include <SkUtils.h>
#include "FontUtil.h"
@@ -271,9 +272,9 @@
if (cachedGlyph) {
// Is the glyph still in texture cache?
if (!cachedGlyph->mIsValid) {
- const SkGlyph& skiaGlyph = GET_METRICS(paint, textUnit,
- &mDescription.mLookupTransform);
- updateGlyphCache(paint, skiaGlyph, cachedGlyph, precaching);
+ SkAutoGlyphCache autoCache(*paint, NULL, &mDescription.mLookupTransform);
+ const SkGlyph& skiaGlyph = GET_METRICS(autoCache.getCache(), textUnit);
+ updateGlyphCache(paint, skiaGlyph, autoCache.getCache(), cachedGlyph, precaching);
}
} else {
cachedGlyph = cacheGlyph(paint, textUnit, precaching);
@@ -415,8 +416,8 @@
}
}
-void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph,
- bool precaching) {
+void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, SkGlyphCache* skiaGlyphCache,
+ CachedGlyphInfo* glyph, bool precaching) {
glyph->mAdvanceX = skiaGlyph.fAdvanceX;
glyph->mAdvanceY = skiaGlyph.fAdvanceY;
glyph->mBitmapLeft = skiaGlyph.fLeft;
@@ -429,7 +430,7 @@
// Get the bitmap for the glyph
if (!skiaGlyph.fImage) {
- paint->findImage(skiaGlyph, &mDescription.mLookupTransform);
+ skiaGlyphCache->findImage(skiaGlyph);
}
mState->cacheBitmap(skiaGlyph, glyph, &startX, &startY, precaching);
@@ -463,11 +464,12 @@
CachedGlyphInfo* newGlyph = new CachedGlyphInfo();
mCachedGlyphs.add(glyph, newGlyph);
- const SkGlyph& skiaGlyph = GET_METRICS(paint, glyph, &mDescription.mLookupTransform);
+ SkAutoGlyphCache autoCache(*paint, NULL, &mDescription.mLookupTransform);
+ const SkGlyph& skiaGlyph = GET_METRICS(autoCache.getCache(), glyph);
newGlyph->mIsValid = false;
newGlyph->mGlyphIndex = skiaGlyph.fID;
- updateGlyphCache(paint, skiaGlyph, newGlyph, precaching);
+ updateGlyphCache(paint, skiaGlyph, autoCache.getCache(), newGlyph, precaching);
return newGlyph;
}
diff --git a/libs/hwui/font/Font.h b/libs/hwui/font/Font.h
index 9e7ec2d..f68b430 100644
--- a/libs/hwui/font/Font.h
+++ b/libs/hwui/font/Font.h
@@ -19,6 +19,7 @@
#include <utils/KeyedVector.h>
+#include <SkGlyphCache.h>
#include <SkScalerContext.h>
#include <SkPaint.h>
#include <SkPathMeasure.h>
@@ -117,8 +118,8 @@
void invalidateTextureCache(CacheTexture* cacheTexture = NULL);
CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph, bool precaching);
- void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph,
- bool precaching);
+ void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, SkGlyphCache* skiaGlyphCache,
+ CachedGlyphInfo* glyph, bool precaching);
void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
diff --git a/libs/hwui/font/FontUtil.h b/libs/hwui/font/FontUtil.h
index cdcb23c..c2fd5f5 100644
--- a/libs/hwui/font/FontUtil.h
+++ b/libs/hwui/font/FontUtil.h
@@ -40,7 +40,7 @@
#if RENDER_TEXT_AS_GLYPHS
typedef uint16_t glyph_t;
#define TO_GLYPH(g) g
- #define GET_METRICS(paint, glyph, matrix) paint->getGlyphMetrics(glyph, matrix)
+ #define GET_METRICS(cache, glyph) cache->getGlyphIDMetrics(glyph)
#define GET_GLYPH(text) nextGlyph((const uint16_t**) &text)
#define IS_END_OF_STRING(glyph) false
@@ -53,7 +53,7 @@
#else
typedef SkUnichar glyph_t;
#define TO_GLYPH(g) ((SkUnichar) g)
- #define GET_METRICS(paint, glyph, matrix) paint->getUnicharMetrics(glyph, matrix)
+ #define GET_METRICS(cache, glyph) cache->getUnicharMetrics(glyph)
#define GET_GLYPH(text) SkUTF16_NextUnichar((const uint16_t**) &text)
#define IS_END_OF_STRING(glyph) glyph < 0
#endif
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 20eb356..9db35fc 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -98,7 +98,7 @@
private static SimpleDateFormat sFormatter;
static {
- System.loadLibrary("exif_jni");
+ System.loadLibrary("jhead_jni");
sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
sFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
}
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index 6dbb3cd..910b24c 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -404,7 +404,7 @@
* @throws IllegalArgumentException
*/
public boolean setSynchronizationMode(int sync) throws IllegalArgumentException {
- if ((sync != POSITION_SYNCHRONIZATION_NONE) || (sync != POSITION_SYNCHRONIZATION_CHECK)) {
+ if ((sync != POSITION_SYNCHRONIZATION_NONE) && (sync != POSITION_SYNCHRONIZATION_CHECK)) {
throw new IllegalArgumentException("Unknown synchronization mode " + sync);
}
if (!mIsRegistered) {
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 63a61e2..dea971e 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -41,13 +41,13 @@
libstagefright_amrnb_common \
LOCAL_REQUIRED_MODULES := \
- libexif_jni
+ libjhead_jni
LOCAL_STATIC_LIBRARIES := \
libstagefright_amrnbenc
LOCAL_C_INCLUDES += \
- external/jhead \
+ external/libexif/ \
external/tremor/Tremor \
frameworks/base/core/jni \
frameworks/av/media/libmedia \
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index d134667..4be9cd6 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -115,6 +115,7 @@
nativeParcel->setData(obj->data(), obj->dataSize());
env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
msg, ext1, ext2, jParcel);
+ env->DeleteLocalRef(jParcel);
}
} else {
env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 77c7966..067e7a6 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -37,7 +37,10 @@
#include "mtp.h"
extern "C" {
-#include "jhead.h"
+#include "libexif/exif-content.h"
+#include "libexif/exif-data.h"
+#include "libexif/exif-tag.h"
+#include "libexif/exif-utils.h"
}
using namespace android;
@@ -750,6 +753,22 @@
return result;
}
+static void foreachentry(ExifEntry *entry, void *user) {
+ char buf[1024];
+ ALOGI("entry %x, format %d, size %d: %s",
+ entry->tag, entry->format, entry->size, exif_entry_get_value(entry, buf, sizeof(buf)));
+}
+
+static void foreachcontent(ExifContent *content, void *user) {
+ ALOGI("content %d", exif_content_get_ifd(content));
+ exif_content_foreach_entry(content, foreachentry, user);
+}
+
+static long getLongFromExifEntry(ExifEntry *e) {
+ ExifByteOrder o = exif_data_get_byte_order(e->parent->parent);
+ return exif_get_long(e->data, o);
+}
+
MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
MtpObjectInfo& info) {
char date[20];
@@ -792,23 +811,22 @@
// read EXIF data for thumbnail information
if (info.mFormat == MTP_FORMAT_EXIF_JPEG || info.mFormat == MTP_FORMAT_JFIF) {
- ResetJpgfile();
- // Start with an empty image information structure.
- memset(&ImageInfo, 0, sizeof(ImageInfo));
- ImageInfo.FlashUsed = -1;
- ImageInfo.MeteringMode = -1;
- ImageInfo.Whitebalance = -1;
- strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX);
- if (ReadJpegFile((const char*)path, READ_METADATA)) {
- Section_t* section = FindSection(M_EXIF);
- if (section) {
- info.mThumbCompressedSize = ImageInfo.ThumbnailSize;
- info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
- info.mImagePixWidth = ImageInfo.Width;
- info.mImagePixHeight = ImageInfo.Height;
- }
+
+ ExifData *exifdata = exif_data_new_from_file(path);
+ if (exifdata) {
+ //exif_data_foreach_content(exifdata, foreachcontent, NULL);
+
+ // XXX get this from exif, or parse jpeg header instead?
+ ExifEntry *w = exif_content_get_entry(
+ exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_X_DIMENSION);
+ ExifEntry *h = exif_content_get_entry(
+ exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_Y_DIMENSION);
+ info.mThumbCompressedSize = exifdata->data ? exifdata->size : 0;
+ info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
+ info.mImagePixWidth = w ? getLongFromExifEntry(w) : 0;
+ info.mImagePixHeight = h ? getLongFromExifEntry(h) : 0;
+ exif_data_unref(exifdata);
}
- DiscardData();
}
checkAndClearExceptionFromCallback(env, __FUNCTION__);
@@ -824,22 +842,16 @@
if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK
&& (format == MTP_FORMAT_EXIF_JPEG || format == MTP_FORMAT_JFIF)) {
- ResetJpgfile();
- // Start with an empty image information structure.
- memset(&ImageInfo, 0, sizeof(ImageInfo));
- ImageInfo.FlashUsed = -1;
- ImageInfo.MeteringMode = -1;
- ImageInfo.Whitebalance = -1;
- strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX);
- if (ReadJpegFile((const char*)path, READ_METADATA)) {
- Section_t* section = FindSection(M_EXIF);
- if (section) {
- outThumbSize = ImageInfo.ThumbnailSize;
- result = malloc(outThumbSize);
- if (result)
- memcpy(result, section->Data + ImageInfo.ThumbnailOffset + 8, outThumbSize);
+
+ ExifData *exifdata = exif_data_new_from_file(path);
+ if (exifdata) {
+ if (exifdata->data) {
+ result = malloc(exifdata->size);
+ if (result) {
+ memcpy(result, exifdata->data, exifdata->size);
+ }
}
- DiscardData();
+ exif_data_unref(exifdata);
}
}
diff --git a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
index 6424744..53f04bc 100644
--- a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
+++ b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
@@ -30,6 +30,7 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
+#include <SkImage.h>
#include <SkMallocPixelRef.h>
#include "omx_jpeg_decoder.h"
@@ -184,8 +185,7 @@
void OmxJpegImageDecoder::configBitmapSize(SkBitmap* bm, SkBitmap::Config pref,
int width, int height) {
- bm->setConfig(getColorSpaceConfig(pref), width, height);
- bm->setIsOpaque(true);
+ bm->setConfig(getColorSpaceConfig(pref), width, height, 0, kOpaque_SkAlphaType);
}
SkBitmap::Config OmxJpegImageDecoder::getColorSpaceConfig(
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index d05f052..a7e0114 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -381,6 +381,7 @@
static final Rect mTmpNavigationFrame = new Rect();
WindowState mTopFullscreenOpaqueWindowState;
+ boolean mHideWindowBehindKeyguard;
boolean mTopIsFullscreen;
boolean mForceStatusBar;
boolean mForceStatusBarFromKeyguard;
@@ -3365,6 +3366,7 @@
@Override
public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
mTopFullscreenOpaqueWindowState = null;
+ mHideWindowBehindKeyguard = false;
mForceStatusBar = false;
mForceStatusBarFromKeyguard = false;
mForcingShowNavBar = false;
@@ -3400,7 +3402,7 @@
if (attrs.type == TYPE_KEYGUARD) {
mShowingLockscreen = true;
}
- boolean applyWindow = attrs.type >= FIRST_APPLICATION_WINDOW
+ boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
&& attrs.type <= LAST_APPLICATION_WINDOW;
if (attrs.type == TYPE_DREAM) {
// If the lockscreen was showing when the dream started then wait
@@ -3408,30 +3410,35 @@
if (!mDreamingLockscreen
|| (win.isVisibleLw() && win.hasDrawnLw())) {
mShowingDream = true;
- applyWindow = true;
+ appWindow = true;
}
}
- if (applyWindow
- && attrs.x == 0 && attrs.y == 0
- && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
- && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
- mTopFullscreenOpaqueWindowState = win;
- if ((attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mHideLockScreen to true by win " + win);
- mHideLockScreen = true;
- mForceStatusBarFromKeyguard = false;
- }
- if ((attrs.flags & FLAG_DISMISS_KEYGUARD) != 0
- && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
- if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mDismissKeyguard true by win " + win);
- mDismissKeyguard = mWinDismissingKeyguard == win ?
- DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
- mWinDismissingKeyguard = win;
- mForceStatusBarFromKeyguard = mShowingLockscreen && isKeyguardSecure();
- }
- if ((attrs.flags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
- mAllowLockscreenWhenOn = true;
+
+ final boolean showWhenLocked = (attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0;
+ if (appWindow) {
+ if (attrs.x == 0 && attrs.y == 0
+ && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
+ && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
+ if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
+ mTopFullscreenOpaqueWindowState = win;
+ if (showWhenLocked && !mHideWindowBehindKeyguard) {
+ if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mHideLockScreen to true by win " + win);
+ mHideLockScreen = true;
+ mForceStatusBarFromKeyguard = false;
+ }
+ if ((attrs.flags & FLAG_DISMISS_KEYGUARD) != 0
+ && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
+ if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mDismissKeyguard true by win " + win);
+ mDismissKeyguard = mWinDismissingKeyguard == win ?
+ DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
+ mWinDismissingKeyguard = win;
+ mForceStatusBarFromKeyguard = mShowingLockscreen && isKeyguardSecure();
+ }
+ if ((attrs.flags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
+ mAllowLockscreenWhenOn = true;
+ }
+ } else if (!showWhenLocked) {
+ mHideWindowBehindKeyguard = true;
}
}
}
@@ -3517,7 +3524,7 @@
if (mKeyguard != null) {
if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
+ mHideLockScreen);
- if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardDelegate.isSecure()) {
+ if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !isKeyguardSecure()) {
if (mKeyguard.hideLw(true)) {
changes |= FINISH_LAYOUT_REDO_LAYOUT
| FINISH_LAYOUT_REDO_CONFIG
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 9201b1d..e2050fc 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1328,7 +1328,7 @@
String pkg = bundle.getString("pkg");
String reason = bundle.getString("reason");
forceStopPackageLocked(pkg, appid, restart, false, true, false,
- UserHandle.USER_ALL, reason);
+ false, UserHandle.USER_ALL, reason);
}
} break;
case FINALIZE_PENDING_INTENT_MSG: {
@@ -4494,7 +4494,7 @@
private void forceStopPackageLocked(final String packageName, int uid, String reason) {
forceStopPackageLocked(packageName, UserHandle.getAppId(uid), false,
- false, true, false, UserHandle.getUserId(uid), reason);
+ false, true, false, false, UserHandle.getUserId(uid), reason);
Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
Uri.fromParts("package", packageName, null));
if (!mProcessesReady) {
@@ -4510,7 +4510,7 @@
}
private void forceStopUserLocked(int userId, String reason) {
- forceStopPackageLocked(null, -1, false, false, true, false, userId, reason);
+ forceStopPackageLocked(null, -1, false, false, true, false, false, userId, reason);
Intent intent = new Intent(Intent.ACTION_USER_STOPPED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
@@ -4595,7 +4595,7 @@
private final boolean forceStopPackageLocked(String name, int appId,
boolean callerWillRestart, boolean purgeCache, boolean doit,
- boolean evenPersistent, int userId, String reason) {
+ boolean evenPersistent, boolean uninstalling, int userId, String reason) {
int i;
int N;
@@ -4687,7 +4687,7 @@
// Remove transient permissions granted from/to this package/user
removeUriPermissionsForPackageLocked(name, userId, false);
- if (name == null) {
+ if (name == null || uninstalling) {
// Remove pending intents. For now we only do this when force
// stopping users, because we have some problems when doing this
// for packages -- app widgets are not currently cleaned up for
@@ -5132,7 +5132,7 @@
if (pkgs != null) {
for (String pkg : pkgs) {
synchronized (ActivityManagerService.this) {
- if (forceStopPackageLocked(pkg, -1, false, false, false, false, 0,
+ if (forceStopPackageLocked(pkg, -1, false, false, false, false, false, 0,
"finished booting")) {
setResultCode(Activity.RESULT_OK);
return;
@@ -8445,7 +8445,7 @@
mDebugTransient = !persistent;
if (packageName != null) {
forceStopPackageLocked(packageName, -1, false, false, true, true,
- UserHandle.USER_ALL, "set debug app");
+ false, UserHandle.USER_ALL, "set debug app");
}
}
} finally {
@@ -9225,8 +9225,13 @@
ActivityInfo ai = ris.get(i).activityInfo;
ComponentName comp = new ComponentName(ai.packageName, ai.name);
if (lastDoneReceivers.contains(comp)) {
+ // We already did the pre boot receiver for this app with the current
+ // platform version, so don't do it again...
ris.remove(i);
i--;
+ // ...however, do keep it as one that has been done, so we don't
+ // forget about it when rewriting the file of last done receivers.
+ doneReceivers.add(comp);
}
}
@@ -13373,7 +13378,7 @@
String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
if (list != null && (list.length > 0)) {
for (String pkg : list) {
- forceStopPackageLocked(pkg, -1, false, true, true, false, userId,
+ forceStopPackageLocked(pkg, -1, false, true, true, false, false, userId,
"storage unmount");
}
sendPackageBroadcastLocked(
@@ -13385,10 +13390,13 @@
if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(
intent.getAction());
+ boolean fullUninstall = removed &&
+ !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
forceStopPackageLocked(ssp, UserHandle.getAppId(
intent.getIntExtra(Intent.EXTRA_UID, -1)), false, true, true,
- false, userId, removed ? "pkg removed" : "pkg changed");
+ false, fullUninstall, userId,
+ removed ? "pkg removed" : "pkg changed");
}
if (removed) {
sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
@@ -13866,7 +13874,7 @@
final long origId = Binder.clearCallingIdentity();
// Instrumentation can kill and relaunch even persistent processes
- forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, userId,
+ forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, false, userId,
"start instr");
ProcessRecord app = addAppLocked(ai, false);
app.instrumentationClass = className;
@@ -13934,7 +13942,7 @@
app.instrumentationProfileFile = null;
app.instrumentationArguments = null;
- forceStopPackageLocked(app.info.packageName, -1, false, false, true, true, app.userId,
+ forceStopPackageLocked(app.info.packageName, -1, false, false, true, true, false, app.userId,
"finished inst");
}
diff --git a/services/java/com/android/server/wifi/WifiController.java b/services/java/com/android/server/wifi/WifiController.java
index a3d514e..bdb0a5e 100644
--- a/services/java/com/android/server/wifi/WifiController.java
+++ b/services/java/com/android/server/wifi/WifiController.java
@@ -152,11 +152,21 @@
addState(mStaDisabledWithScanState, mDefaultState);
addState(mApEnabledState, mDefaultState);
addState(mEcmState, mDefaultState);
- if (mSettingsStore.isScanAlwaysAvailable()) {
+
+ boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn();
+ boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled();
+ boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();
+
+ log("isAirplaneModeOn = " + isAirplaneModeOn +
+ ", isWifiEnabled = " + isWifiEnabled +
+ ", isScanningAvailable = " + isScanningAlwaysAvailable);
+
+ if (isWifiEnabled && isScanningAlwaysAvailable) {
setInitialState(mStaDisabledWithScanState);
} else {
setInitialState(mApStaDisabledState);
}
+
setLogRecSize(100);
setLogOnlyTransitions(false);
diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java
index f2efde1..aecf9ae 100644
--- a/services/java/com/android/server/wifi/WifiService.java
+++ b/services/java/com/android/server/wifi/WifiService.java
@@ -870,7 +870,7 @@
public void setCountryCode(String countryCode, boolean persist) {
Slog.i(TAG, "WifiService trying to set country code to " + countryCode +
" with persist set to " + persist);
- enforceChangePermission();
+ enforceConnectivityInternalPermission();
final long token = Binder.clearCallingIdentity();
try {
mWifiStateMachine.setCountryCode(countryCode, persist);
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index eedd66f..3dda56a 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -233,6 +233,10 @@
private DhcpStateMachine mDhcpStateMachine;
private boolean mDhcpActive = false;
+ // Delay in switching to null country code (non-null has no delay)
+ private final int COUNTRY_CODE_DELAY_MS = 15000;
+ private final AtomicInteger mCountryCodeSequence = new AtomicInteger();
+
private class InterfaceObserver extends BaseNetworkObserver {
private WifiStateMachine mWifiStateMachine;
@@ -1534,14 +1538,15 @@
* @param persist {@code true} if the setting should be remembered.
*/
public void setCountryCode(String countryCode, boolean persist) {
- if (persist) {
- mPersistedCountryCode = countryCode;
- Settings.Global.putString(mContext.getContentResolver(),
- Settings.Global.WIFI_COUNTRY_CODE,
- countryCode);
+ // If it's a country code, apply immediately,
+ // If it's empty, delay it in case it's a momentary dropout
+ int countryCodeSequence = mCountryCodeSequence.incrementAndGet();
+ if (TextUtils.isEmpty(countryCode)) {
+ sendMessageDelayed(CMD_SET_COUNTRY_CODE, countryCodeSequence, persist ? 1 : 0,
+ countryCode, COUNTRY_CODE_DELAY_MS);
+ } else {
+ sendMessage(CMD_SET_COUNTRY_CODE, countryCodeSequence, persist ? 1 : 0, countryCode);
}
- sendMessage(CMD_SET_COUNTRY_CODE, countryCode);
- mWifiP2pChannel.sendMessage(WifiP2pService.SET_COUNTRY_CODE, countryCode);
}
/**
@@ -2507,7 +2512,9 @@
// to the driver happened between mPersistedCountryCode getting set
// and now, so simply persisting it here would mean we have sent
// nothing to the driver. Send the cmd so it might be set now.
- sendMessageAtFrontOfQueue(CMD_SET_COUNTRY_CODE, countryCode);
+ int sequenceNum = mCountryCodeSequence.incrementAndGet();
+ sendMessageAtFrontOfQueue(CMD_SET_COUNTRY_CODE,
+ sequenceNum, 0, countryCode);
}
break;
case CMD_SET_BATCHED_SCAN:
@@ -3090,18 +3097,29 @@
break;
case CMD_SET_COUNTRY_CODE:
String country = (String) message.obj;
+ final boolean persist = (message.arg2 == 1);
+ final int sequence = message.arg1;
+ if (sequence != mCountryCodeSequence.get()) {
+ if (DBG) log("set country code ignored due to sequence num");
+ break;
+ }
if (DBG) log("set country code " + country);
- if (country != null) {
- country = country.toUpperCase(Locale.ROOT);
- if (mLastSetCountryCode == null
- || country.equals(mLastSetCountryCode) == false) {
- if (mWifiNative.setCountryCode(country)) {
- mLastSetCountryCode = country;
- } else {
- loge("Failed to set country code " + country);
- }
+ if (persist) {
+ mPersistedCountryCode = country;
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.WIFI_COUNTRY_CODE,
+ country);
+ }
+ country = country.toUpperCase(Locale.ROOT);
+ if (mLastSetCountryCode == null
+ || country.equals(mLastSetCountryCode) == false) {
+ if (mWifiNative.setCountryCode(country)) {
+ mLastSetCountryCode = country;
+ } else {
+ loge("Failed to set country code " + country);
}
}
+ mWifiP2pChannel.sendMessage(WifiP2pService.SET_COUNTRY_CODE, country);
break;
case CMD_SET_FREQUENCY_BAND:
int band = message.arg1;