From cfb8048f3a1deff8ebcfcec9fdfcda8467997f50 Mon Sep 17 00:00:00 2001 From: Srikanth Katta Date: Tue, 11 Jun 2013 18:28:31 +0530 Subject: [PATCH 001/204] frameworks/base: Add support for FM feature. - Added changes for FM device Change-Id: I5dcb820e910d5fdb755aa92de10b1948c70a2e46 --- media/java/android/media/AudioSystem.java | 14 ++++++++++++++ media/java/android/media/MediaRecorder.java | 17 ++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 5e88ba5fa2ba7..5848684d22c84 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -232,6 +232,8 @@ private static void errorCallbackFromNative(int error) public static final int DEVICE_OUT_ANC_HEADSET = 0x10000; public static final int DEVICE_OUT_ANC_HEADPHONE = 0x20000; public static final int DEVICE_OUT_PROXY = 0x40000; + public static final int DEVICE_OUT_FM = 0x80000; + public static final int DEVICE_OUT_FM_TX = 0x100000; public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT; public static final int DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE | @@ -253,6 +255,8 @@ private static void errorCallbackFromNative(int error) DEVICE_OUT_ANC_HEADSET | DEVICE_OUT_ANC_HEADPHONE | DEVICE_OUT_PROXY | + DEVICE_OUT_FM | + DEVICE_OUT_FM_TX | DEVICE_OUT_DEFAULT); public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP | DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | @@ -279,6 +283,8 @@ private static void errorCallbackFromNative(int error) public static final int DEVICE_IN_USB_DEVICE = DEVICE_BIT_IN | 0x1000; public static final int DEVICE_IN_ANC_HEADSET = DEVICE_BIT_IN | 0x2000; public static final int DEVICE_IN_PROXY = DEVICE_BIT_IN | 0x4000; + public static final int DEVICE_IN_FM_RX = DEVICE_BIT_IN | 0x8000; + public static final int DEVICE_IN_FM_RX_A2DP = DEVICE_BIT_IN | 0x10000; public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT; public static final int DEVICE_IN_ALL = (DEVICE_IN_COMMUNICATION | @@ -296,6 +302,8 @@ private static void errorCallbackFromNative(int error) DEVICE_IN_USB_DEVICE | DEVICE_IN_ANC_HEADSET | DEVICE_IN_PROXY | + DEVICE_IN_FM_RX | + DEVICE_IN_FM_RX_A2DP | DEVICE_IN_DEFAULT); public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET; @@ -323,6 +331,8 @@ private static void errorCallbackFromNative(int error) public static final String DEVICE_OUT_ANC_HEADSET_NAME = "anc_headset"; public static final String DEVICE_OUT_ANC_HEADPHONE_NAME = "anc_headphone"; public static final String DEVICE_OUT_PROXY_NAME = "proxy"; + public static final String DEVICE_OUT_FM_NAME = "fm"; + public static final String DEVICE_OUT_FM_TX_NAME = "fm_tx"; public static String getDeviceName(int device) { @@ -365,6 +375,10 @@ public static String getDeviceName(int device) return DEVICE_OUT_ANC_HEADPHONE_NAME; case DEVICE_OUT_PROXY: return DEVICE_OUT_PROXY_NAME; + case DEVICE_OUT_FM: + return DEVICE_OUT_FM_NAME; + case DEVICE_OUT_FM_TX: + return DEVICE_OUT_FM_TX_NAME; case DEVICE_OUT_DEFAULT: default: return ""; diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 0d78fe8832183..75af5249c2a3f 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -179,6 +179,18 @@ private AudioSource() {} * is applied. */ public static final int VOICE_COMMUNICATION = 7; + + /** + * @hide + * Audio source for remote submix. + */ + public static final int REMOTE_SUBMIX_SOURCE = 8; + + /** @hide */ + public static final int FM_RX = 9; + + /** @hide */ + public static final int FM_RX_A2DP = 10; } /** @@ -307,7 +319,10 @@ public native void setAudioSource(int audio_source) * @see android.media.MediaRecorder.AudioSource */ public static final int getAudioSourceMax() { - return AudioSource.VOICE_COMMUNICATION; + // FIXME disable selection of the remote submxi source selection once test code + // doesn't rely on it + return AudioSource.FM_RX_A2DP; + //return AudioSource.VOICE_COMMUNICATION; } /** From 0c82481e783a2fa7d97bbd6140be3f8c3642e4e0 Mon Sep 17 00:00:00 2001 From: Wink Saville Date: Sat, 21 Sep 2013 09:01:19 -0700 Subject: [PATCH 002/204] Do not always call setIsConnectedToProvisioningNetwork(false) Previously I was calling setIsConnectedToProvisioningNetwork(false) always, but all MDST's receive every broadcast. Thus we could over write an MDST's mNetworkInfo.mIsConnectedToProvisioningNetwork to false, unless the MDST that was set to true was last, i.e the code was order dependent. If the provisioning networks value was false instead of true when handleMobileProvisioningAction was called we wouldn't invoke mdst.enableMobileProvisioning because network info would be null. Thus the provisioning network would never transition to CONNECTED and a default route wouldn't get setup and the browser couldn't access the website. Now setIsConnectedToProvisioningNetwork is only set to false when the apnType matches and we won't indiscriminately change it and are not order dependent. Bug: 10853805 Change-Id: I68a4f9bdf5dc18d90f4cdef7a60811f57be67261 --- core/java/android/net/MobileDataStateTracker.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java index e09254b18419c..b2b5314b281b3 100644 --- a/core/java/android/net/MobileDataStateTracker.java +++ b/core/java/android/net/MobileDataStateTracker.java @@ -190,8 +190,6 @@ private void updateLinkProperitesAndCapatilities(Intent intent) { private class MobileDataStateReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - // Assume this isn't a provisioning network. - mNetworkInfo.setIsConnectedToProvisioningNetwork(false); if (intent.getAction().equals(TelephonyIntents. ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN)) { String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY); @@ -218,6 +216,8 @@ public void onReceive(Context context, Intent intent) { if (!TextUtils.equals(apnType, mApnType)) { return; } + // Assume this isn't a provisioning network. + mNetworkInfo.setIsConnectedToProvisioningNetwork(false); if (DBG) { log("Broadcast received: " + intent.getAction() + " apnType=" + apnType); } @@ -299,6 +299,8 @@ public void onReceive(Context context, Intent intent) { if (!TextUtils.equals(apnType, mApnType)) { return; } + // Assume this isn't a provisioning network. + mNetworkInfo.setIsConnectedToProvisioningNetwork(false); String reason = intent.getStringExtra(PhoneConstants.FAILURE_REASON_KEY); String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY); if (DBG) { From b04dc7fe91465ee93cdb414af0247a948d5d5f07 Mon Sep 17 00:00:00 2001 From: Ondrej Zima Date: Tue, 24 Sep 2013 15:03:59 +0200 Subject: [PATCH 003/204] base: CS translation - added blocks for ADB over network Change-Id: I5d58002eae4ae2b04abc0d6b4fda3d903fc2ebff --- packages/SystemUI/res/values-cs/cm_strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/SystemUI/res/values-cs/cm_strings.xml b/packages/SystemUI/res/values-cs/cm_strings.xml index 6f8114ad0acea..0544e582933df 100644 --- a/packages/SystemUI/res/values-cs/cm_strings.xml +++ b/packages/SystemUI/res/values-cs/cm_strings.xml @@ -48,6 +48,8 @@ LTE vyp. Hlasitost Fotoaparát + Zakázáno + Povoleno Rozšířený Normální Fotoaparát nelze spustit From 2c4086ecc97342c71070e651788053c6ec3f9495 Mon Sep 17 00:00:00 2001 From: MatoDroid Date: Mon, 30 Sep 2013 18:24:53 +0200 Subject: [PATCH 004/204] SystemUI: SK translations Change-Id: I2a3155f4300a4eedf55f0b0d204185052af90d62 --- .../SystemUI/res/values-sk/cm_strings.xml | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/packages/SystemUI/res/values-sk/cm_strings.xml b/packages/SystemUI/res/values-sk/cm_strings.xml index f3f22986d53d1..70699067060ac 100644 --- a/packages/SystemUI/res/values-sk/cm_strings.xml +++ b/packages/SystemUI/res/values-sk/cm_strings.xml @@ -18,13 +18,13 @@ HSPA+ Zvuk %s. Vibrácie %s. - Použiť hlavičku Cid - Použije hlavičku Cid namiesto vnútornej hlavičky jellybean + Použiť hlavičku Cida + Použiť hlavičku Cida namiesto sladkých želé fazulí Profil Časový limit obrazovky bol nastavený na: %1$d %2$s GPS GPS vyp. - Go to sleep + Spánok Zvuk zap. Zvuk vyp. Vibrácie zap. @@ -37,14 +37,14 @@ Nahlásiť chybu Synch. Synch. vyp. - Torch - Torch vyp. + Svietidlo + Svietidlo vyp. NFC NFC vyp. Časový limit Odpojené - Tethering off - Tethering + Zdieľanie vyp. + Zdieľanie Wi-Fi AP Wi-Fi AP vyp. Čas ticha @@ -57,18 +57,20 @@ Vyberte akciu na priradenie Fotoaparát Nemožno sa pripojiť k fotoaparátu - Tlačidlo domov - Tlačidlo nedávne - Tlačidlo hľadať - Tlačidlo späť + Tlačidlo Domov + Tlačidlo Nedávne + Tlačidlo Hľadať + Tlačidlo Späť Prázdne tlačidlo - Tlačidlo ponuky (autom. skrývané) - Tlačidlo ponuky (stále viditeľné) - Tlačidlo ponuky + Tlačidlo Ponuka (autom. skrývané) + Tlačidlo Ponuka (stále viditeľné) + Tlačidlo Ponuka Nabíjanie (%d%%) Nabitá %d%% zostáva Žiadna služba - Režim v lietadle zap. + Režim V lietadle zap. Iba tiesňové volania + Batéria %d%%. + DCHSPAP From fb1205ffc4742956c8b48df05310ed8d2de46ba0 Mon Sep 17 00:00:00 2001 From: Marco Brohet Date: Sat, 5 Oct 2013 13:36:14 +0200 Subject: [PATCH 005/204] SystemUI: NL translations Change-Id: I421d1687491f42fe7b5f029a5a9a540a5c51db9a --- packages/SystemUI/res/values-nl/cm_strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/SystemUI/res/values-nl/cm_strings.xml b/packages/SystemUI/res/values-nl/cm_strings.xml index 8e9f1be210cd4..4cd3c740a8144 100644 --- a/packages/SystemUI/res/values-nl/cm_strings.xml +++ b/packages/SystemUI/res/values-nl/cm_strings.xml @@ -35,6 +35,8 @@ LTE uit Volume Camera + Uitgeschakeld + Ingeschakeld Uitgebreid Normaal Kan geen verbinding maken met de camera. From 4dcf1a6f5498f1bddfe1f1498c6eeca6d393b07a Mon Sep 17 00:00:00 2001 From: isimobile Date: Fri, 20 Sep 2013 19:47:16 +0200 Subject: [PATCH 006/204] Frameworks_base: Add AF Translations Change-Id: Ib03427c8d753c7e3412063fc1312a4c2c886ef7a --- core/res/res/values-af/cm_strings.xml | 11 +++++- .../InputDevices/res/values-af/cm_strings.xml | 35 +++++++++++++++++++ .../SystemUI/res/values-af/cm_strings.xml | 2 ++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 packages/InputDevices/res/values-af/cm_strings.xml diff --git a/core/res/res/values-af/cm_strings.xml b/core/res/res/values-af/cm_strings.xml index 358123db9faed..33977a1d459eb 100644 --- a/core/res/res/values-af/cm_strings.xml +++ b/core/res/res/values-af/cm_strings.xml @@ -46,7 +46,10 @@ Laat die program toe om die FM-ontvanger te beheer. Beheer FM-sender Laat die program toe om die FM-sender te beheer. + Stuur skyn-SMS boodskappe + Laat die program skyn-SMS boodskappe stuur. Dit laat \'n program toe om SMS te stuur na betroubare programme. Kwaadwillige programme kan boodskappe voortdurend stuur, dan dit sal die kennisgewings stelsel blokkeer en die gebruiker ontwrig. %d%% ontlaai + Geen verwyderbare media beskikbaar nie\u2026 Dok SD-kaart Program beëindig Herlaai @@ -60,7 +63,13 @@ %1$s het nie toegang tot persoonlike data nie Profiele Geen - onderskep uitgaande SMS + Onderskep uitgaande SMS Laat \'n program toe om uitgaande SMS boodskappe te onderskep. Kwaadwillige programme kan die reg misbruik om uitgaande SMS boodskappe te verhoed. + Kanselleer program kennisgewings + Laat die program toe om kennisgewings geskep deur ander programme te kanselleer. + Dwing SELinux af + Wissel SELinux beleid: Dwing of permissiewe mode. + Dwing MMAC + Wissel MMAC beleid: Dwing of permissiewe mode. diff --git a/packages/InputDevices/res/values-af/cm_strings.xml b/packages/InputDevices/res/values-af/cm_strings.xml new file mode 100644 index 0000000000000..d5ddbfcc7a37b --- /dev/null +++ b/packages/InputDevices/res/values-af/cm_strings.xml @@ -0,0 +1,35 @@ + + + Invoertoestelle + Android sleutelbord + Engels (VK) + Engels (VSA) + Engels (VSA), Dvorak styl + Duits + Frans + Frans (Kanada) + Russiese + Russiese, Mac styl + Spaans + Switserse Frans + Switserse Duits + Belgiese + Bulgaarse + Italiaanse + Deense + Noorweegse + Sweedse + Finse + Kroaties + Tsjeggiese + Estonian + Hongaarse + Yslandse + Portugees + Slovak + Slovenia + Turks + Oekraïens + Engels (VSA), Colemak styl + Armenian Oosterse + diff --git a/packages/SystemUI/res/values-af/cm_strings.xml b/packages/SystemUI/res/values-af/cm_strings.xml index d52cb676f41ba..d6f39ac6ce628 100644 --- a/packages/SystemUI/res/values-af/cm_strings.xml +++ b/packages/SystemUI/res/values-af/cm_strings.xml @@ -46,6 +46,8 @@ LTE af Volume Kamera + Gedeaktiveer + Aktiveer Kies \'n aksie om toe te ken Tuis-knoppie Onlangse programme knoppie From decbe1a6176f65e17fd66f059f58398aa605b3b3 Mon Sep 17 00:00:00 2001 From: Gaurav Asati Date: Mon, 19 Aug 2013 19:03:51 +0530 Subject: [PATCH 007/204] Bluetooth: Support HFP Client role on Bluedroid. Implementation changes to support HFP Client role on Bluedroid stack. Change-Id: Ie37e95d3b0e3f785af818fb495c835e420792f4d --- Android.mk | 1 + .../android/bluetooth/BluetoothAdapter.java | 9 + .../bluetooth/BluetoothHandsfreeClient.java | 1158 +++++++++++++++++ .../BluetoothHandsfreeClientCall.aidl | 20 + .../BluetoothHandsfreeClientCall.java | 205 +++ .../android/bluetooth/BluetoothProfile.java | 8 + .../bluetooth/IBluetoothHandsfreeClient.aidl | 69 + 7 files changed, 1470 insertions(+) create mode 100644 core/java/android/bluetooth/BluetoothHandsfreeClient.java create mode 100644 core/java/android/bluetooth/BluetoothHandsfreeClientCall.aidl create mode 100644 core/java/android/bluetooth/BluetoothHandsfreeClientCall.java create mode 100644 core/java/android/bluetooth/IBluetoothHandsfreeClient.aidl diff --git a/Android.mk b/Android.mk index e31e23f5c2154..5094048850dcb 100644 --- a/Android.mk +++ b/Android.mk @@ -101,6 +101,7 @@ LOCAL_SRC_FILES += \ core/java/android/bluetooth/IBluetoothManagerCallback.aidl \ core/java/android/bluetooth/IBluetoothPbap.aidl \ core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \ + core/java/android/bluetooth/IBluetoothHandsfreeClient.aidl \ core/java/android/bluetooth/IBluetoothGatt.aidl \ core/java/android/bluetooth/IBluetoothGattCallback.aidl \ core/java/android/bluetooth/IBluetoothGattServerCallback.aidl \ diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 229f41f0977fc..104f6653da4ca 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -1,4 +1,6 @@ /* + * Copyright (C) 2013 The Linux Foundation. All rights reserved + * Not a Contribution. * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -1184,6 +1186,9 @@ public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener } else if (profile == BluetoothProfile.HEALTH) { BluetoothHealth health = new BluetoothHealth(context, listener); return true; + } else if (profile == BluetoothProfile.HANDSFREE_CLIENT) { + BluetoothHandsfreeClient hfpclient = new BluetoothHandsfreeClient(context, listener); + return true; } else { return false; } @@ -1236,6 +1241,10 @@ public void closeProfileProxy(int profile, BluetoothProfile proxy) { BluetoothGattServer gattServer = (BluetoothGattServer)proxy; gattServer.close(); break; + case BluetoothProfile.HANDSFREE_CLIENT: + BluetoothHandsfreeClient hfpclient = (BluetoothHandsfreeClient)proxy; + hfpclient.close(); + break; } } diff --git a/core/java/android/bluetooth/BluetoothHandsfreeClient.java b/core/java/android/bluetooth/BluetoothHandsfreeClient.java new file mode 100644 index 0000000000000..dd4212a6825fd --- /dev/null +++ b/core/java/android/bluetooth/BluetoothHandsfreeClient.java @@ -0,0 +1,1158 @@ +/* + * Copyright (C) 2013 The Linux Foundation. All rights reserved + * Not a Contribution. + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; + +/** + * Public API to control Hands Free Profile (HFP role only). + *

+ * This class defines methods that shall be used by application to manage profile + * connection, calls states and calls actions. + *

+ * + * @hide + * */ +public final class BluetoothHandsfreeClient implements BluetoothProfile { + private static final String TAG = "BluetoothHandsfreeClient"; + private static final boolean DBG = true; + private static final boolean VDBG = false; + + /** + * Intent sent whenever connection to remote changes. + * + *

It includes two extras: + * BluetoothProfile.EXTRA_PREVIOUS_STATE + * and BluetoothProfile.EXTRA_STATE, which + * are mandatory. + *

There are also non mandatory feature extras: + * {@link #EXTRA_AG_FEATURE_3WAY_CALLING}, + * {@link #EXTRA_AG_FEATURE_VOICE_RECOGNITION}, + * {@link #EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT}, + * {@link #EXTRA_AG_FEATURE_REJECT_CALL}, + * {@link #EXTRA_AG_FEATURE_ECC}, + * {@link #EXTRA_AG_FEATURE_RESPONSE_AND_HOLD}, + * {@link #EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL}, + * {@link #EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL}, + * {@link #EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT}, + * {@link #EXTRA_AG_FEATURE_MERGE}, + * {@link #EXTRA_AG_FEATURE_MERGE_AND_DETACH}, + * sent as boolean values only when EXTRA_STATE + * is set to STATE_CONNECTED.

+ * + *

Note that features supported by AG are being sent as + * booleans with value true, + * and not supported ones are not being sent at all.

+ */ + public static final String ACTION_CONNECTION_STATE_CHANGED = + "org.codeaurora.handsfreeclient.profile.action.CONNECTION_STATE_CHANGED"; + + /** + * Intent sent whenever audio state changes. + * + *

It includes two mandatory extras: + * {@link BluetoothProfile.EXTRA_STATE}, + * {@link BluetoothProfile.EXTRA_PREVIOUS_STATE}, + * with possible values: + * {@link #STATE_AUDIO_CONNECTING}, + * {@link #STATE_AUDIO_CONNECTED}, + * {@link #STATE_AUDIO_DISCONNECTED}

+ *

When EXTRA_STATE is set + * to STATE_AUDIO_CONNECTED, + * it also includes {@link #EXTRA_AUDIO_WBS} + * indicating wide band speech support.

+ */ + public static final String ACTION_AUDIO_STATE_CHANGED = + "org.codeaurora.handsfreeclient.profile.action.AUDIO_STATE_CHANGED"; + + /** + * Intent sending updates of the Audio Gateway state. + * Each extra is being sent only when value it + * represents has been changed recently on AG. + *

It can contain one or more of the following extras: + * {@link #EXTRA_NETWORK_STATUS}, + * {@link #EXTRA_NETWORK_SIGNAL_STRENGTH}, + * {@link #EXTRA_NETWORK_ROAMING}, + * {@link #EXTRA_BATTERY_LEVEL}, + * {@link #EXTRA_OPERATOR_NAME}, + * {@link #EXTRA_VOICE_RECOGNITION}, + * {@link #EXTRA_IN_BAND_RING}

+ */ + public static final String ACTION_AG_EVENT = + "org.codeaurora.handsfreeclient.profile.action.AG_EVENT"; + + /** + * Intent sent whenever state of a call changes. + * + *

It includes: + * {@link #EXTRA_CALL}, + * with value of {@link BluetoothHandsfreeClientCall} instance, + * representing actual call state.

+ */ + public static final String ACTION_CALL_CHANGED = + "org.codeaurora.handsfreeclient.profile.action.AG_CALL_CHANGED"; + + /** + * Intent that notifies about the result of the last issued action. + * Please note that not every action results in explicit action result code being sent. + * Instead other notifications about new Audio Gateway state might be sent, + * like ACTION_AG_EVENT with EXTRA_VOICE_RECOGNITION value + * when for example user started voice recognition from HF unit. + */ + public static final String ACTION_RESULT = + "org.codeaurora.handsfreeclient.profile.action.RESULT"; + + /** + * Intent that notifies about the number attached to the last voice tag + * recorded on AG. + * + *

It contains: + * {@link #EXTRA_NUMBER}, + * with a String value representing phone number.

+ */ + public static final String ACTION_LAST_VTAG = + "org.codeaurora.handsfreeclient.profile.action.LAST_VTAG"; + + public static final int STATE_AUDIO_DISCONNECTED = 0; + public static final int STATE_AUDIO_CONNECTING = 1; + public static final int STATE_AUDIO_CONNECTED = 2; + + /** + * Extra with information if connected audio is WBS. + *

Possible values: true, + * false.

+ */ + public static final String EXTRA_AUDIO_WBS = + "android.bluetooth.handsfreeclient.extra.AUDIO_WBS"; + + /** + * Extra for AG_EVENT indicates network status. + *

Value: 0 - network unavailable, + * 1 - network available

+ */ + public static final String EXTRA_NETWORK_STATUS = + "android.bluetooth.handsfreeclient.extra.NETWORK_STATUS"; + /** + * Extra for AG_EVENT intent indicates network signal strength. + *

Value: Integer representing signal strength.

+ */ + public static final String EXTRA_NETWORK_SIGNAL_STRENGTH = + "android.bluetooth.handsfreeclient.extra.NETWORK_SIGNAL_STRENGTH"; + /** + * Extra for AG_EVENT intent indicates roaming state. + *

Value: 0 - no roaming + * 1 - active roaming

+ */ + public static final String EXTRA_NETWORK_ROAMING = + "android.bluetooth.handsfreeclient.extra.NETWORK_ROAMING"; + /** + * Extra for AG_EVENT intent indicates the battery level. + *

Value: Integer representing signal strength.

+ */ + public static final String EXTRA_BATTERY_LEVEL = + "android.bluetooth.handsfreeclient.extra.BATTERY_LEVEL"; + /** + * Extra for AG_EVENT intent indicates operator name. + *

Value: String representing operator name.

+ */ + public static final String EXTRA_OPERATOR_NAME = + "android.bluetooth.handsfreeclient.extra.OPERATOR_NAME"; + /** + * Extra for AG_EVENT intent indicates voice recognition state. + *

Value: + * 0 - voice recognition stopped, + * 1 - voice recognition started.

+ */ + public static final String EXTRA_VOICE_RECOGNITION = + "android.bluetooth.handsfreeclient.extra.VOICE_RECOGNITION"; + /** + * Extra for AG_EVENT intent indicates in band ring state. + *

Value: + * 0 - in band ring tone not supported, or + * 1 - in band ring tone supported.

+ */ + public static final String EXTRA_IN_BAND_RING = + "android.bluetooth.handsfreeclient.extra.IN_BAND_RING"; + + /** + * Extra for AG_EVENT intent indicates subscriber info. + *

Value: String containing subscriber information.

+ */ + public static final String EXTRA_SUBSCRIBER_INFO = + "android.bluetooth.handsfreeclient.extra.SUBSCRIBER_INFO"; + + /** + * Extra for AG_CALL_CHANGED intent indicates the + * {@link BluetoothHandsfreeClientCall} object that has changed. + */ + public static final String EXTRA_CALL = + "android.bluetooth.handsfreeclient.extra.CALL"; + + /** + * Extra for ACTION_LAST_VTAG intent. + *

Value: String representing phone number + * corresponding to last voice tag recorded on AG

+ */ + public static final String EXTRA_NUMBER = + "android.bluetooth.handsfreeclient.extra.NUMBER"; + + /** + * Extra for ACTION_RESULT intent that shows the result code of + * last issued action. + *

Possible results: + * {@link #ACTION_RESULT_OK}, + * {@link #ACTION_RESULT_ERROR}, + * {@link #ACTION_RESULT_ERROR_NO_CARRIER}, + * {@link #ACTION_RESULT_ERROR_BUSY}, + * {@link #ACTION_RESULT_ERROR_NO_ANSWER}, + * {@link #ACTION_RESULT_ERROR_DELAYED}, + * {@link #ACTION_RESULT_ERROR_BLACKLISTED}, + * {@link #ACTION_RESULT_ERROR_CME}

+ */ + public static final String EXTRA_RESULT_CODE = + "android.bluetooth.handsfreeclient.extra.RESULT_CODE"; + + /** + * Extra for ACTION_RESULT intent that shows the extended result code of + * last issued action. + *

Value: Integer - error code.

+ */ + public static final String EXTRA_CME_CODE = + "android.bluetooth.handsfreeclient.extra.CME_CODE"; + + /* Extras for AG_FEATURES, extras type is boolean */ + // TODO verify if all of those are actually useful + /** + * AG feature: three way calling. + */ + public final static String EXTRA_AG_FEATURE_3WAY_CALLING = + "android.bluetooth.handsfreeclient.extra.EXTRA_AG_FEATURE_3WAY_CALLING"; + /** + * AG feature: voice recognition. + */ + public final static String EXTRA_AG_FEATURE_VOICE_RECOGNITION = + "android.bluetooth.handsfreeclient.extra.EXTRA_AG_FEATURE_VOICE_RECOGNITION"; + /** + * AG feature: fetching phone number for voice tagging procedure. + */ + public final static String EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT = + "android.bluetooth.handsfreeclient.extra.EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT"; + /** + * AG feature: ability to reject incoming call. + */ + public final static String EXTRA_AG_FEATURE_REJECT_CALL = + "android.bluetooth.handsfreeclient.extra.EXTRA_AG_FEATURE_REJECT_CALL"; + /** + * AG feature: enhanced call handling (terminate specific call, private consultation). + */ + public final static String EXTRA_AG_FEATURE_ECC = + "android.bluetooth.handsfreeclient.extra.EXTRA_AG_FEATURE_ECC"; + /** + * AG feature: response and hold. + */ + public final static String EXTRA_AG_FEATURE_RESPONSE_AND_HOLD = + "android.bluetooth.handsfreeclient.extra.EXTRA_AG_FEATURE_RESPONSE_AND_HOLD"; + /** + * AG call handling feature: accept held or waiting call in three way calling scenarios. + */ + public final static String EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL = + "android.bluetooth.handsfreeclient.extra.EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL"; + /** + * AG call handling feature: release held or waiting call in three way calling scenarios. + */ + public final static String EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL = + "android.bluetooth.handsfreeclient.extra.EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL"; + /** + * AG call handling feature: release active call and accept held or waiting call in three way calling scenarios. + */ + public final static String EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT = + "android.bluetooth.handsfreeclient.extra.EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT"; + /** + * AG call handling feature: merge two calls, held and active - multi party conference mode. + */ + public final static String EXTRA_AG_FEATURE_MERGE = + "android.bluetooth.handsfreeclient.extra.EXTRA_AG_FEATURE_MERGE"; + /** + * AG call handling feature: merge calls and disconnect from multi party + * conversation leaving peers connected to each other. + * Note that this feature needs to be supported by mobile network operator + * as it requires connection and billing transfer. + */ + public final static String EXTRA_AG_FEATURE_MERGE_AND_DETACH = + "android.bluetooth.handsfreeclient.extra.EXTRA_AG_FEATURE_MERGE_AND_DETACH"; + + /* Action result codes */ + public final static int ACTION_RESULT_OK = 0; + public final static int ACTION_RESULT_ERROR = 1; + public final static int ACTION_RESULT_ERROR_NO_CARRIER = 2; + public final static int ACTION_RESULT_ERROR_BUSY = 3; + public final static int ACTION_RESULT_ERROR_NO_ANSWER = 4; + public final static int ACTION_RESULT_ERROR_DELAYED = 5; + public final static int ACTION_RESULT_ERROR_BLACKLISTED = 6; + public final static int ACTION_RESULT_ERROR_CME = 7; + + /* Detailed CME error codes */ + public final static int CME_PHONE_FAILURE = 0; + public final static int CME_NO_CONNECTION_TO_PHONE = 1; + public final static int CME_OPERATION_NOT_ALLOWED = 3; + public final static int CME_OPERATION_NOT_SUPPORTED = 4; + public final static int CME_PHSIM_PIN_REQUIRED = 5; + public final static int CME_PHFSIM_PIN_REQUIRED = 6; + public final static int CME_PHFSIM_PUK_REQUIRED = 7; + public final static int CME_SIM_NOT_INSERTED = 10; + public final static int CME_SIM_PIN_REQUIRED = 11; + public final static int CME_SIM_PUK_REQUIRED = 12; + public final static int CME_SIM_FAILURE = 13; + public final static int CME_SIM_BUSY = 14; + public final static int CME_SIM_WRONG = 15; + public final static int CME_INCORRECT_PASSWORD = 16; + public final static int CME_SIM_PIN2_REQUIRED = 17; + public final static int CME_SIM_PUK2_REQUIRED = 18; + public final static int CME_MEMORY_FULL = 20; + public final static int CME_INVALID_INDEX = 21; + public final static int CME_NOT_FOUND = 22; + public final static int CME_MEMORY_FAILURE = 23; + public final static int CME_TEXT_STRING_TOO_LONG = 24; + public final static int CME_INVALID_CHARACTER_IN_TEXT_STRING = 25; + public final static int CME_DIAL_STRING_TOO_LONG = 26; + public final static int CME_INVALID_CHARACTER_IN_DIAL_STRING = 27; + public final static int CME_NO_NETWORK_SERVICE = 30; + public final static int CME_NETWORK_TIMEOUT = 31; + public final static int CME_EMERGENCY_SERVICE_ONLY = 32; + public final static int CME_NO_SIMULTANOUS_VOIP_CS_CALLS = 33; + public final static int CME_NOT_SUPPORTED_FOR_VOIP = 34; + public final static int CME_SIP_RESPONSE_CODE = 35; + public final static int CME_NETWORK_PERSONALIZATION_PIN_REQUIRED = 40; + public final static int CME_NETWORK_PERSONALIZATION_PUK_REQUIRED = 41; + public final static int CME_NETWORK_SUBSET_PERSONALIZATION_PIN_REQUIRED = 42; + public final static int CME_NETWORK_SUBSET_PERSONALIZATION_PUK_REQUIRED = 43; + public final static int CME_SERVICE_PROVIDER_PERSONALIZATION_PIN_REQUIRED = 44; + public final static int CME_SERVICE_PROVIDER_PERSONALIZATION_PUK_REQUIRED = 45; + public final static int CME_CORPORATE_PERSONALIZATION_PIN_REQUIRED = 46; + public final static int CME_CORPORATE_PERSONALIZATION_PUK_REQUIRED = 47; + public final static int CME_HIDDEN_KEY_REQUIRED = 48; + public final static int CME_EAP_NOT_SUPPORTED = 49; + public final static int CME_INCORRECT_PARAMETERS = 50; + + /* Action policy for other calls when accepting call */ + public static final int CALL_ACCEPT_NONE = 0; + public static final int CALL_ACCEPT_HOLD = 1; + public static final int CALL_ACCEPT_TERMINATE = 2; + + private Context mContext; + private ServiceListener mServiceListener; + private IBluetoothHandsfreeClient mService; + private BluetoothAdapter mAdapter; + + final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + @Override + public void onBluetoothStateChange(boolean up) { + if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); + if (!up) { + if (VDBG) Log.d(TAG,"Unbinding service..."); + synchronized (mConnection) { + try { + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } else { + synchronized (mConnection) { + try { + if (mService == null) { + if (VDBG) Log.d(TAG,"Binding service..."); + if (!mContext.bindService(new Intent(IBluetoothHandsfreeClient.class.getName()), mConnection, 0)) { + Log.e(TAG, "Could not bind to Bluetooth Handsfree Client Service"); + } + } + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + } + }; + + /** + * Create a BluetoothHandsfreeClient proxy object. + */ + /*package*/ BluetoothHandsfreeClient(Context context, ServiceListener l) { + mContext = context; + mServiceListener = l; + mAdapter = BluetoothAdapter.getDefaultAdapter(); + + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); + } catch (RemoteException e) { + Log.e(TAG,"",e); + } + } + + if (!context.bindService(new Intent(IBluetoothHandsfreeClient.class.getName()), mConnection, 0)) { + Log.e(TAG, "Could not bind to Bluetooth Handsfree Client Service"); + } + } + + /** + * Close the connection to the backing service. + * Other public functions of BluetoothHandsfreeClient will return default error + * results once close() has been called. Multiple invocations of close() + * are ok. + */ + /*package*/ void close() { + if (VDBG) log("close()"); + + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); + } catch (Exception e) { + Log.e(TAG,"",e); + } + } + + synchronized (mConnection) { + if (mService != null) { + try { + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + mServiceListener = null; + } + + /** + * Connects to remote device. + * + * Currently, the system supports only 1 connection. So, in case of the + * second connection, this implementation will disconnect already connected + * device automatically and will process the new one. + * + * @param device a remote device we want connect to + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} + * intent. + */ + public boolean connect(BluetoothDevice device) { + if (DBG) log("connect(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.connect(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Disconnects remote device + * + * @param device a remote device we want disconnect + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_CONNECTION_STATE_CHANGED} + * intent. + */ + public boolean disconnect(BluetoothDevice device) { + if (DBG) log("disconnect(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.disconnect(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Return the list of connected remote devices + * + * @return list of connected devices; empty list if nothing is connected. + */ + @Override + public List getConnectedDevices() { + if (VDBG) log("getConnectedDevices()"); + if (mService != null && isEnabled()) { + try { + return mService.getConnectedDevices(); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return new ArrayList(); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList(); + } + + /** + * Returns list of remote devices in a particular state + * + * @param states collection of states + * @return list of devices that state matches the states listed in + * states; empty list if nothing matches the + * states + */ + @Override + public List getDevicesMatchingConnectionStates(int[] states) { + if (VDBG) log("getDevicesMatchingStates()"); + if (mService != null && isEnabled()) { + try { + return mService.getDevicesMatchingConnectionStates(states); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return new ArrayList(); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return new ArrayList(); + } + + /** + * Returns state of the device + * + * @param device a remote device + * @return the state of connection of the device + */ + @Override + public int getConnectionState(BluetoothDevice device) { + if (VDBG) log("getConnectionState(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.getConnectionState(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return BluetoothProfile.STATE_DISCONNECTED; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return BluetoothProfile.STATE_DISCONNECTED; + } + + /** + * Set priority of the profile + * + * The device should already be paired. + */ + public boolean setPriority(BluetoothDevice device, int priority) { + if (DBG) log("setPriority(" + device + ", " + priority + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + if (priority != BluetoothProfile.PRIORITY_OFF && + priority != BluetoothProfile.PRIORITY_ON) { + return false; + } + try { + return mService.setPriority(device, priority); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Get the priority of the profile. + */ + public int getPriority(BluetoothDevice device) { + if (VDBG) log("getPriority(" + device + ")"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.getPriority(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return PRIORITY_OFF; + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return PRIORITY_OFF; + } + + /** + * Starts voice recognition. + * + * @param device remote device + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_AG_EVENT} + * intent. + * + *

Feature required for successful execution is being reported by: + * {@link #EXTRA_AG_FEATURE_VOICE_RECOGNITION}. + * This method invocation will fail silently when feature is not supported.

+ */ + public boolean startVoiceRecognition(BluetoothDevice device) { + if (DBG) log("startVoiceRecognition()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.startVoiceRecognition(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Stops voice recognition. + * + * @param device remote device + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_AG_EVENT} + * intent. + * + *

Feature required for successful execution is being reported by: + * {@link #EXTRA_AG_FEATURE_VOICE_RECOGNITION}. + * This method invocation will fail silently when feature is not supported.

+ */ + public boolean stopVoiceRecognition(BluetoothDevice device) { + if (DBG) log("stopVoiceRecognition()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.stopVoiceRecognition(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Returns list of all calls in any state. + * + * @param device remote device + * @return list of calls; empty list if none call exists + */ + public List getCurrentCalls(BluetoothDevice device) { + if (DBG) log("getCurrentCalls()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.getCurrentCalls(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return null; + } + + /** + * Returns list of current values of AG indicators. + * + * @param device remote device + * @return bundle of AG indicators; null if device is not in + * CONNECTED state + */ + public Bundle getCurrentAgEvents(BluetoothDevice device) { + if (DBG) log("getCurrentCalls()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.getCurrentAgEvents(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return null; + } + + /** + * Accepts a call + * + * @param device remote device + * @param flag action policy while accepting a call. Possible values + * {@link #CALL_ACCEPT_NONE}, {@link #CALL_ACCEPT_HOLD}, + * {@link #CALL_ACCEPT_TERMINATE} + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent. + */ + public boolean acceptCall(BluetoothDevice device, int flag) { + if (DBG) log("acceptCall()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.acceptCall(device, flag); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Holds a call. + * + * @param device remote device + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent. + */ + public boolean holdCall(BluetoothDevice device) { + if (DBG) log("holdCall()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.holdCall(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Rejects a call. + * + * @param device remote device + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent. + * + *

Feature required for successful execution is being reported by: + * {@link #EXTRA_AG_FEATURE_REJECT_CALL}. + * This method invocation will fail silently when feature is not supported.

+ */ + public boolean rejectCall(BluetoothDevice device) { + if (DBG) log("rejectCall()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.rejectCall(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Terminates a specified call. + * + * Works only when Extended Call Control is supported by Audio Gateway. + * + * @param device remote device + * @param index index of the call to be terminated + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent. + * + *

Feature required for successful execution is being reported by: + * {@link #EXTRA_AG_FEATURE_ECC}. + * This method invocation will fail silently when feature is not supported.

+ */ + public boolean terminateCall(BluetoothDevice device, int index) { + if (DBG) log("terminateCall()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.terminateCall(device, index); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Enters private mode with a specified call. + * + * Works only when Extended Call Control is supported by Audio Gateway. + * + * @param device remote device + * @param index index of the call to connect in private mode + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent. + * + *

Feature required for successful execution is being reported by: + * {@link #EXTRA_AG_FEATURE_ECC}. + * This method invocation will fail silently when feature is not supported.

+ */ + public boolean enterPrivateMode(BluetoothDevice device, int index) { + if (DBG) log("enterPrivateMode()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.enterPrivateMode(device, index); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Performs explicit call transfer. + * + * That means connect other calls and disconnect. + * + * @param device remote device + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent. + * + *

Feature required for successful execution is being reported by: + * {@link #EXTRA_AG_FEATURE_MERGE_AND_DETACH}. + * This method invocation will fail silently when feature is not supported.

+ */ + public boolean explicitCallTransfer(BluetoothDevice device) { + if (DBG) log("explicitCallTransfer()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.explicitCallTransfer(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Redials last number from Audio Gateway. + * + * @param device remote device + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent in case of success; {@link #ACTION_RESULT} is sent + * otherwise; + */ + public boolean redial(BluetoothDevice device) { + if (DBG) log("redial()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.redial(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Places a call with specified number. + * + * @param device remote device + * @param number valid phone number + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent in case of success; {@link #ACTION_RESULT} is sent + * otherwise; + */ + public boolean dial(BluetoothDevice device, String number) { + if (DBG) log("dial()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.dial(device, number); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Places a call to the number under specified memory location. + * + * @param device remote device + * @param location valid memory location + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_CALL_CHANGED} + * intent in case of success; {@link #ACTION_RESULT} is sent + * otherwise; + */ + public boolean dialMemory(BluetoothDevice device, int location) { + if (DBG) log("dialMemory()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.dialMemory(device, location); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Sends DTMF code. + * + * Possible code values : 0,1,2,3,4,5,6,7,8,9,A,B,C,D,*,# + * + * @param device remote device + * @param code ASCII code + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_RESULT} intent; + */ + public boolean sendDTMF(BluetoothDevice device, byte code) { + if (DBG) log("sendDTMF()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.sendDTMF(device, code); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Get a number corresponding to last voice tag recorded on AG. + * + * @param device remote device + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_LAST_VTAG} + * or {@link #ACTION_RESULT} intent; + * + *

Feature required for successful execution is being reported by: + * {@link #EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT}. + * This method invocation will fail silently when feature is not supported.

+ */ + public boolean getLastVoiceTagNumber(BluetoothDevice device) { + if (DBG) log("getLastVoiceTagNumber()"); + if (mService != null && isEnabled() && + isValidDevice(device)) { + try { + return mService.getLastVoiceTagNumber(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + } + } + if (mService == null) Log.w(TAG, "Proxy not attached to service"); + return false; + } + + /** + * Accept the incoming connection. + */ + public boolean acceptIncomingConnect(BluetoothDevice device) { + if (DBG) log("acceptIncomingConnect"); + if (mService != null && isEnabled()) { + try { + return mService.acceptIncomingConnect(device); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** + * Reject the incoming connection. + */ + public boolean rejectIncomingConnect(BluetoothDevice device) { + if (DBG) log("rejectIncomingConnect"); + if (mService != null) { + try { + return mService.rejectIncomingConnect(device); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** + * Returns current audio state of Audio Gateway. + * + * Note: This is an internal function and shouldn't be exposed + */ + public int getAudioState(BluetoothDevice device) { + if (VDBG) log("getAudioState"); + if (mService != null && isEnabled()) { + try { + return mService.getAudioState(device); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return BluetoothHandsfreeClient.STATE_AUDIO_DISCONNECTED; + } + + /** + * Initiates a connection of audio channel. + * + * It setup SCO channel with remote connected Handsfree AG device. + * + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} + * intent; + */ + public boolean connectAudio() { + if (mService != null && isEnabled()) { + try { + return mService.connectAudio(); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** + * Disconnects audio channel. + * + * It tears down the SCO channel from remote AG device. + * + * @return true if command has been issued successfully; + * false otherwise; + * upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} + * intent; + */ + public boolean disconnectAudio() { + if (mService != null && isEnabled()) { + try { + return mService.disconnectAudio(); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** + * Get Audio Gateway features + * + * @param device remote device + * @return bundle of AG features; null if no service or + * AG not connected + */ + public Bundle getCurrentAgFeatures(BluetoothDevice device) { + if (mService != null && isEnabled()) { + try { + return mService.getCurrentAgFeatures(device); + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return null; + } + + + private ServiceConnection mConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName className, IBinder service) { + if (DBG) Log.d(TAG, "Proxy object connected"); + mService = IBluetoothHandsfreeClient.Stub.asInterface(service); + + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothProfile.HANDSFREE_CLIENT, BluetoothHandsfreeClient.this); + } + } + @Override + public void onServiceDisconnected(ComponentName className) { + if (DBG) Log.d(TAG, "Proxy object disconnected"); + mService = null; + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(BluetoothProfile.HANDSFREE_CLIENT); + } + } + }; + + private boolean isEnabled() { + if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; + return false; + } + + private boolean isValidDevice(BluetoothDevice device) { + if (device == null) return false; + + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; + return false; + } + + private static void log(String msg) { + Log.d(TAG, msg); + } +} diff --git a/core/java/android/bluetooth/BluetoothHandsfreeClientCall.aidl b/core/java/android/bluetooth/BluetoothHandsfreeClientCall.aidl new file mode 100644 index 0000000000000..ca90385a8dcb3 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothHandsfreeClientCall.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2013 The Linux Foundation. All rights reserved + * Not a Contribution. + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.bluetooth; + +parcelable BluetoothHandsfreeClientCall; diff --git a/core/java/android/bluetooth/BluetoothHandsfreeClientCall.java b/core/java/android/bluetooth/BluetoothHandsfreeClientCall.java new file mode 100644 index 0000000000000..872ab6be0c9b6 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothHandsfreeClientCall.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Linux Foundation nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package android.bluetooth; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * This class represents a single call, its state and properties. + * It implements {@link Parcelable} for inter-process message passing. + * @hide + */ +public final class BluetoothHandsfreeClientCall implements Parcelable { + + /* Call state */ + /** + * Call is active. + */ + public static final int CALL_STATE_ACTIVE = 0; + /** + * Call is in held state. + */ + public static final int CALL_STATE_HELD = 1; + /** + * Outgoing call that is being dialed right now. + */ + public static final int CALL_STATE_DIALING = 2; + /** + * Outgoing call that remote party has already been alerted about. + */ + public static final int CALL_STATE_ALERTING = 3; + /** + * Incoming call that can be accepted or rejected. + */ + public static final int CALL_STATE_INCOMING = 4; + /** + * Waiting call state when there is already an active call. + */ + public static final int CALL_STATE_WAITING = 5; + /** + * Call that has been held by response and hold + * (see Bluetooth specification for further references). + */ + public static final int CALL_STATE_HELD_BY_RESPONSE_AND_HOLD = 6; + /** + * Call that has been already terminated and should not be referenced as a valid call. + */ + public static final int CALL_STATE_TERMINATED = 7; + + private final int mId; + private int mState; + private String mNumber; + private boolean mMultiParty; + private final boolean mOutgoing; + + /** + * Creates BluetoothHandsfreeClientCall instance. + */ + public BluetoothHandsfreeClientCall(int id, int state, String number, boolean multiParty, + boolean outgoing) { + mId = id; + mState = state; + mNumber = number != null ? number : ""; + mMultiParty = multiParty; + mOutgoing = outgoing; + } + + /** + * Sets call's state. + * + *

Note: This is an internal function and shouldn't be exposed

+ * + * @param state new call state. + */ + public void setState(int state) { + mState = state; + } + + /** + * Sets call's number. + * + *

Note: This is an internal function and shouldn't be exposed

+ * + * @param number String representing phone number. + */ + public void setNumber(String number) { + mNumber = number; + } + + /** + * Sets this call as multi party call. + * + *

Note: This is an internal function and shouldn't be exposed

+ * + * @param multiParty if true sets this call as a part + * of multi party conference. + */ + public void setMultiParty(boolean multiParty) { + mMultiParty = multiParty; + } + + /** + * Gets call's Id. + * + * @return call id. + */ + public int getId() { + return mId; + } + + /** + * Gets call's current state. + * + * @return state of this particular phone call. + */ + public int getState() { + return mState; + } + + /** + * Gets call's number. + * + * @return string representing phone number. + */ + public String getNumber() { + return mNumber; + } + + /** + * Checks if call is an active call in a conference mode (aka multi party). + * + * @return true if call is a multi party call, + * false otherwise. + */ + public boolean isMultiParty() { + return mMultiParty; + } + + /** + * Checks if this call is an outgoing call. + * + * @return true if its outgoing call, + * false otherwise. + */ + public boolean isOutgoing() { + return mOutgoing; + } + + /** + * {@link Parcelable.Creator} interface implementation. + */ + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public BluetoothHandsfreeClientCall createFromParcel(Parcel in) { + return new BluetoothHandsfreeClientCall(in.readInt(), in.readInt(), + in.readString(), in.readInt() == 1, in.readInt() == 1); + } + + @Override + public BluetoothHandsfreeClientCall[] newArray(int size) { + return new BluetoothHandsfreeClientCall[size]; + } + }; + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mId); + out.writeInt(mState); + out.writeString(mNumber); + out.writeInt(mMultiParty ? 1 : 0); + out.writeInt(mOutgoing ? 1 : 0); + } + + @Override + public int describeContents() { + return 0; + } +} diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index 7c2ea6e466180..80266d5362234 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -1,4 +1,6 @@ /* + * Copyright (C) 2013 The Linux Foundation. All rights reserved + * Not a Contribution. * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -103,6 +105,12 @@ public interface BluetoothProfile { */ public static final int SAP = 20; + /** + * Handsfree Client - HFP HF Role + * @hide + */ + public static final int HANDSFREE_CLIENT = 9; + /** * Default priority for devices that we try to auto-connect to and * and allow incoming connections for the profile diff --git a/core/java/android/bluetooth/IBluetoothHandsfreeClient.aidl b/core/java/android/bluetooth/IBluetoothHandsfreeClient.aidl new file mode 100644 index 0000000000000..1e660ae1b18ee --- /dev/null +++ b/core/java/android/bluetooth/IBluetoothHandsfreeClient.aidl @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2013 The Linux Foundation. All rights reserved + * Not a Contribution. + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth; + +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothHandsfreeClientCall; +import android.os.Bundle; + +/** + * API for Bluetooth Handsfree Client service (HFP HF Role) + * + * {@hide} + */ +interface IBluetoothHandsfreeClient { + boolean connect(in BluetoothDevice device); + boolean disconnect(in BluetoothDevice device); + + boolean acceptIncomingConnect(in BluetoothDevice device); + boolean rejectIncomingConnect(in BluetoothDevice device); + + List getConnectedDevices(); + List getDevicesMatchingConnectionStates(in int[] states); + int getConnectionState(in BluetoothDevice device); + boolean setPriority(in BluetoothDevice device, int priority); + int getPriority(in BluetoothDevice device); + + boolean startVoiceRecognition(in BluetoothDevice device); + boolean stopVoiceRecognition(in BluetoothDevice device); + + List getCurrentCalls(in BluetoothDevice device); + Bundle getCurrentAgEvents(in BluetoothDevice device); + + boolean acceptCall(in BluetoothDevice device, int flag); + boolean holdCall(in BluetoothDevice device); + boolean rejectCall(in BluetoothDevice device); + boolean terminateCall(in BluetoothDevice device, int index); + + boolean enterPrivateMode(in BluetoothDevice device, int index); + boolean explicitCallTransfer(in BluetoothDevice device); + + boolean redial(in BluetoothDevice device); + boolean dial(in BluetoothDevice device, String number); + boolean dialMemory(in BluetoothDevice device, int location); + + boolean sendDTMF(in BluetoothDevice device, byte code); + boolean getLastVoiceTagNumber(in BluetoothDevice device); + + int getAudioState(in BluetoothDevice device); + boolean connectAudio(); + boolean disconnectAudio(); + + Bundle getCurrentAgFeatures(in BluetoothDevice device); +} From 3716068ce64fb3d539fe3fc133852fe75a842fe7 Mon Sep 17 00:00:00 2001 From: Niranjan Pendharkar Date: Sun, 27 Jan 2013 18:46:22 -0800 Subject: [PATCH 008/204] server: add enhanced routing support Add support for policy and metric based routing APIs to NetworkManagementService. This functionality is used for WQE, IMS, and Android QoS features. Change-Id: I5e50185c9ac1cf72c9366815c2ecf590842edfca --- .../android/os/INetworkManagementService.aidl | 27 ++++ .../server/NetworkManagementService.java | 142 ++++++++++++++++++ 2 files changed, 169 insertions(+) diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 45524c82c9e27..07fdc445b4eb2 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -1,6 +1,10 @@ /* //device/java/android/android/os/INetworkManagementService.aidl ** ** Copyright 2007, The Android Open Source Project +** Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. +** +** Not a Contribution. Apache license notifications and license are +** retained for attribution purposes only. ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -367,4 +371,27 @@ interface INetworkManagementService * Determine whether the clatd (464xlat) service has been started */ boolean isClatdStarted(); + + /** + ** Policy Routing + **/ + + /** + * Replaces a prexisting identical route with the new metric specified. + * Adds a new route if none existed before. + */ + boolean addRouteWithMetric(String iface, int metric, in RouteInfo route); + + /** + * Replaces a source policy route for the given iface in a custom routing + * table denoted by routeId, if it already exists. + * Adds a new route if it did not exist. + */ + boolean replaceSrcRoute(String iface, in byte[] ip, in byte[] gateway, int routeId); + + /** + * Deletes a source policy route for the given route identifier and source + * address from a custom routing table denoted by routeId + */ + boolean delSrcRoute(in byte[] ip, int routeId); } diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index 9fe2faf9e7833..d577ea7a56d2f 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -1,5 +1,9 @@ /* * Copyright (C) 2007 The Android Open Source Project + * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. + * + * Not a Contribution. Apache license notifications and license are + * retained for attribution purposes only. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,6 +56,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; +import android.text.TextUtils; import android.util.Log; import android.util.Slog; import android.util.SparseBooleanArray; @@ -72,10 +77,12 @@ import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.InterfaceAddress; import java.net.NetworkInterface; import java.net.SocketException; +import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -115,6 +122,7 @@ class NetdResponseCode { public static final int TetherDnsFwdTgtListResult = 112; public static final int TtyListResult = 113; + public static final int CommandOkay = 200; public static final int TetherStatusResult = 210; public static final int IpFwdStatusResult = 211; public static final int InterfaceGetCfgResult = 213; @@ -1559,4 +1567,138 @@ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.print("Firewall enabled: "); pw.println(mFirewallEnabled); } + + @Override + public boolean replaceSrcRoute(String iface, byte[] ip, byte[] gateway, int routeId) { + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + final NativeDaemonEvent rsp; + InetAddress ipAddr; + + if (TextUtils.isEmpty(iface)) { + Log.e(TAG,"route cmd failed - iface is invalid"); + return false; + } + + try { + ipAddr = InetAddress.getByAddress(ip); + } catch (UnknownHostException e) { + Log.e(TAG,"route cmd failed because of unknown src ip", e); + return false; + } + + final Command cmd = new Command("route", "replace", "src"); + + if (ipAddr instanceof Inet4Address) + cmd.appendArg("v4"); + else + cmd.appendArg("v6"); + + cmd.appendArg(iface); + cmd.appendArg(ipAddr.getHostAddress()); + cmd.appendArg(routeId); + + try { + InetAddress gatewayAddr = InetAddress.getByAddress(gateway); + // check validity of gw address - add route without gw if its invalid + if ((ipAddr instanceof Inet4Address && gatewayAddr instanceof Inet4Address) || + (ipAddr instanceof Inet6Address && gatewayAddr instanceof Inet6Address)) + { + cmd.appendArg(gatewayAddr.getHostAddress()); + } + } catch (UnknownHostException e) { + Log.w(TAG,"route cmd did not obtain valid gw; adding route without gw"); + } + + try { + rsp = mConnector.execute(cmd); + } catch (NativeDaemonConnectorException e) { + Log.w(TAG,"route cmd failed: ", e); + return false; + } + if (DBG) { + Slog.v(TAG, "replace src route response is " + rsp.toString()); + } + return true; + } + + @Override + public boolean delSrcRoute(byte[] ip, int routeId) { + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + final NativeDaemonEvent rsp; + InetAddress ipAddr; + + try { + ipAddr = InetAddress.getByAddress(ip); + } catch (UnknownHostException e) { + Log.e(TAG,"route cmd failed due to invalid src ip", e); + return false; //cannot remove src route without valid src prefix + } + + final Command cmd = new Command("route", "del", "src"); + + if (ipAddr instanceof Inet4Address) { + cmd.appendArg("v4"); + } else { + cmd.appendArg("v6"); + } + + cmd.appendArg(routeId); + + try { + rsp = mConnector.execute(cmd); + } catch (NativeDaemonConnectorException e) { + Log.w(TAG,"route cmd failed: ", e); + return false; + } + if (DBG) { + Slog.v(TAG, "del src route response is " + rsp.toString()); + } + return true; + } + + @Override + public boolean addRouteWithMetric(String iface, int metric, RouteInfo route) { + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + final NativeDaemonEvent rsp; + + if (TextUtils.isEmpty(iface)) { + Log.e(TAG,"route cmd failed - iface is invalid"); + return false; + } + + final Command cmd = new Command("route", "add"); + if (route.isDefaultRoute()) { + cmd.appendArg("def"); + } else { + cmd.appendArg("dst"); + } + + InetAddress gateway = route.getGateway(); + if (gateway instanceof Inet4Address) { + cmd.appendArg("v4"); + } else { + cmd.appendArg("v6"); + } + + cmd.appendArg(iface); + cmd.appendArg(metric); + + if (route.isHostRoute()) { + cmd.appendArg(route.getDestination().getAddress().getHostAddress()); + } + + cmd.appendArg(gateway.getHostAddress()); + + try { + rsp = mConnector.execute(cmd); + } catch (NativeDaemonConnectorException e) { + Log.w(TAG,"route cmd failed: ", e); + return false; + } + + if (DBG) { + Slog.v(TAG, "add metric route response is " + rsp.toString()); + } + return true; + } } From fd00589e2ef1a50b34e605115c089c6616575252 Mon Sep 17 00:00:00 2001 From: Harout Hedeshian Date: Fri, 28 Jun 2013 14:21:19 -0600 Subject: [PATCH 009/204] frameworks/base: IPV6 tethering support This patch adds two new API calls addUpstreamV6Interface and removeUpstreamV6Interface to the tethering framework to pass the IPv6 upstream and downstream interfaces to netd if IPv6 is available. Required to enable ICMPv6 forwarding. Change-Id: I1f4f6284b2f152d8b4f0fbd02ac5a17f57c71dd7 --- .../android/os/INetworkManagementService.aidl | 10 +++ .../server/NetworkManagementService.java | 35 +++++++++ .../server/connectivity/Tethering.java | 72 ++++++++++++++++++- 3 files changed, 115 insertions(+), 2 deletions(-) diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 07fdc445b4eb2..f70694f231275 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -192,6 +192,16 @@ interface INetworkManagementService */ void disableNat(String internalInterface, String externalInterface); + /** + * Add an upstream IPv6 interface + */ + void addUpstreamV6Interface(String iface); + + /** + * Remove an upstream IPv6 interface + */ + void removeUpstreamV6Interface(String iface); + /** ** PPPD **/ diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index d577ea7a56d2f..2c0ee3f0fc157 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -60,6 +60,7 @@ import android.util.Log; import android.util.Slog; import android.util.SparseBooleanArray; +import java.util.List; import com.android.internal.net.NetworkStatsFactory; import com.android.internal.util.Preconditions; @@ -133,6 +134,7 @@ class NetdResponseCode { public static final int TetheringStatsResult = 221; public static final int DnsProxyQueryResult = 222; public static final int ClatdStatusResult = 223; + public static final int V6RtrAdvResult = 224; public static final int InterfaceChange = 600; public static final int BandwidthControl = 601; @@ -493,6 +495,39 @@ public String[] listInterfaces() { } } + @Override + public void addUpstreamV6Interface(String iface) throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); + + Slog.d(TAG, "addUpstreamInterface("+ iface + ")"); + try { + final Command cmd = new Command("tether", "interface", "add_upstream"); + cmd.appendArg(iface); + mConnector.execute(cmd); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException("Cannot add upstream interface"); + } + } + + @Override + public void removeUpstreamV6Interface(String iface) throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService"); + + Slog.d(TAG, "removeUpstreamInterface(" + iface + ")"); + + try { + final Command cmd = new Command("tether", "interface", "add_upstream"); + cmd.appendArg(iface); + mConnector.execute(cmd); + + mConnector.execute(cmd); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException("Cannot remove upstream interface"); + } + } + @Override public InterfaceConfiguration getInterfaceConfig(String iface) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java index 080b3c682e006..790f19dfd0698 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/java/com/android/server/connectivity/Tethering.java @@ -545,7 +545,7 @@ public void onReceive(Context content, Intent intent) { if (networkInfo != null && networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) { if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION"); - mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED); + mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED, networkInfo); } } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { updateConfiguration(); @@ -1318,7 +1318,55 @@ protected boolean turnOffMasterTetherSettings() { return true; } + protected void addUpstreamV6Interface(String iface) { + IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); + INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); + + Log.d(TAG, "adding v6 interface " + iface); + try { + service.addUpstreamV6Interface(iface); + } catch (Exception e) { + Log.e(TAG, "Unable to append v6 upstream interface", e); + } + } + + protected void removeUpstreamV6Interface(String iface) { + IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); + INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); + + Log.d(TAG, "removing v6 interface " + iface); + try { + service.removeUpstreamV6Interface(iface); + } catch (Exception e) { + Log.e(TAG, "Unable to remove v6 upstream interface", e); + } + } + + + boolean isIpv6Connected(IConnectivityManager cm, LinkProperties linkProps) { + boolean ret = false; + Collection addresses = null; + + if (cm == null || linkProps == null) { + return false; + } + addresses = linkProps.getAddresses(); + for (InetAddress addr: addresses) { + if (addr instanceof java.net.Inet6Address) { + java.net.Inet6Address i6addr = (java.net.Inet6Address) addr; + if (!i6addr.isAnyLocalAddress() && !i6addr.isLinkLocalAddress() && + !i6addr.isLoopbackAddress() && !i6addr.isMulticastAddress()) { + ret = true; + break; + } + } + } + return ret; + } + protected void chooseUpstreamType(boolean tryCell) { + IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); + IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); int upType = ConnectivityManager.TYPE_NONE; String iface = null; @@ -1334,11 +1382,20 @@ protected void chooseUpstreamType(boolean tryCell) { for (Integer netType : mUpstreamIfaceTypes) { NetworkInfo info = null; + LinkProperties props = null; + boolean isV6Connected = false; try { - info = mConnService.getNetworkInfo(netType.intValue()); + info = cm.getNetworkInfo(netType.intValue()); + if (info != null) { + props = cm.getLinkProperties(info.getType()); + isV6Connected = isIpv6Connected(cm, props); + } } catch (RemoteException e) { } if ((info != null) && info.isConnected()) { upType = netType.intValue(); + if (isV6Connected) { + addUpstreamV6Interface(props.getInterfaceName()); + } break; } } @@ -1510,8 +1567,19 @@ public boolean processMessage(Message message) { break; case CMD_UPSTREAM_CHANGED: // need to try DUN immediately if Wifi goes down + NetworkInfo info = (NetworkInfo) message.obj; mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; chooseUpstreamType(mTryCell); + if (!info.isConnected()) { + IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); + IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); + try { + LinkProperties props = cm.getLinkProperties(info.getType()); + removeUpstreamV6Interface(props.getInterfaceName()); + } catch(Exception e) { + Log.e(TAG, "Exception querying ConnectivityManager", e); + } + } mTryCell = !mTryCell; break; case CMD_CELL_CONNECTION_RENEW: From 50db7bc3653200a7e53644b963e3098d1292e367 Mon Sep 17 00:00:00 2001 From: Deepthi Gowri Date: Tue, 16 Jul 2013 19:53:54 +0530 Subject: [PATCH 010/204] Revert "wifi: Get full scan results" This reverts commit b301684e954b6a1659bf7395b1732b658f2fc27e CRs-fixed: 509553 Change-Id: Idafcf1ae25c2b9af42f71ee417cf73601c3199a7 --- wifi/java/android/net/wifi/WifiNative.java | 2 +- .../java/android/net/wifi/WifiStateMachine.java | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java index d1ea213735579..7773a261bea89 100644 --- a/wifi/java/android/net/wifi/WifiNative.java +++ b/wifi/java/android/net/wifi/WifiNative.java @@ -212,7 +212,7 @@ public String getMacAddress() { * RANGE=ID- gets results from ID * MASK= see wpa_supplicant/src/common/wpa_ctrl.h for details */ - public String scanResults(int sid) { + public String scanResults (int sid) { return doStringCommand("BSS RANGE=" + sid + "- MASK=0x21987"); } diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 981902f7b0d15..24846ccb46d9d 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -1421,9 +1421,9 @@ private void setWifiApState(int wifiApState) { private static final String DELIMITER_STR = "===="; private static final String END_STR = "####"; + /** * Format: - * * id=1 * bssid=68:7f:76:d7:1a:6e * freq=2412 @@ -1464,22 +1464,21 @@ private void setScanResults() { if (lines[i].startsWith(END_STR)) { break; } else if (lines[i].startsWith(ID_STR)) { - try { - sid = Integer.parseInt(lines[i].substring(ID_STR.length())) + 1; - } catch (NumberFormatException e) { - // Nothing to do - } - break; + try { + sid = Integer.parseInt(lines[i].substring(ID_STR.length())) + 1; + } catch (NumberFormatException e) { + // Nothing to do + } + break; } } if (sid == -1) break; - } + } scanResults = scanResultsBuf.toString(); if (TextUtils.isEmpty(scanResults)) { return; } - synchronized(mScanResultCache) { mScanResults = new ArrayList(); String[] lines = scanResults.split("\n"); From 727182293409b080265f8ccb8175c57a90371c93 Mon Sep 17 00:00:00 2001 From: Deepthi Gowri Date: Fri, 19 Jul 2013 12:59:03 +0530 Subject: [PATCH 011/204] wifi: LTECoex changes for SAP/P2P Restart sap/P2P GO with safe channel list received from android telephony layer, whenever sap/P2P GO is operating on an channel interfering with LTE. Change-Id: I3f5da86374dcb542ab4f11ac755eca0b2dc067c1 CRs-Fixed: 510273 --- .../android/os/INetworkManagementService.aidl | 15 +++ .../server/NetworkManagementService.java | 81 ++++++++++++++++ wifi/java/android/net/wifi/WifiNative.java | 21 +++++ .../android/net/wifi/WifiStateMachine.java | 93 ++++++++++++++++++- .../android/net/wifi/p2p/WifiP2pGroup.java | 19 ++++ .../android/net/wifi/p2p/WifiP2pService.java | 86 ++++++++++++++++- 6 files changed, 313 insertions(+), 2 deletions(-) diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index f70694f231275..293c8974d12f2 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -404,4 +404,19 @@ interface INetworkManagementService * address from a custom routing table denoted by routeId */ boolean delSrcRoute(in byte[] ip, int routeId); + + /** + * Set SAP Channel Range + */ + void setChannelRange(int startchannel, int endchannel, int band); + + /** + * Get SAP Current Operating Channel + */ + int getSapOperatingChannel(); + + /** + * Get SAP Auto Channel Selection + */ + int getSapAutoChannelSelection(); } diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index 2c0ee3f0fc157..a5a7cc390baa4 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -1082,6 +1082,87 @@ public void stopAccessPoint(String wlanIface) { } } + /*Set SAP Channel Range*/ + public void setChannelRange(int startchannel, int endchannel, int band) + throws IllegalStateException { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); + try { + Slog.d(TAG, "Set SAP Channel Range"); + mConnector.execute( + "softap", "qccmd", "set", "setchannelrange=", startchannel, " ", endchannel, " ", band); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Error communicating to native daemon to set channel range", e); + } + } + + /*Get SAP Operating Channel*/ + public int getSapOperatingChannel() throws IllegalStateException{ + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); + int channel=0; + try { + final NativeDaemonEvent OperChanResp; + Slog.d(TAG, "getSapOperatingChannel"); + OperChanResp = mConnector.execute("softap", "qccmd", "get", "channel"); + Slog.d(TAG, "getSapOperatingChannel--OperChanResp" + OperChanResp); + + //Resp Pattern : 200 8 success channel=6 + final StringTokenizer tok = new StringTokenizer(OperChanResp.getMessage()); + tok.nextToken(); + String temp = (tok.hasMoreTokens()) ? tok.nextToken() : null; + if (temp != null) { + final StringTokenizer tok1 = new StringTokenizer(temp, "="); + String temp1 = (tok1.hasMoreTokens()) ? tok1.nextToken() : null; + String temp2 = (tok1.hasMoreTokens()) ? tok1.nextToken() : null; + if (temp2 != null) + channel = Integer.parseInt(temp2); + } + Slog.d(TAG, "softap qccmd get channel =" + channel); + return channel; + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Error communicating to native daemon to getSapOperatingChannel", e); + } + } + + /*Get SAP Auto Channel Selection*/ + public int getSapAutoChannelSelection() throws IllegalStateException{ + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService"); + int autochannel=0; + try { + final NativeDaemonEvent OperChanResp; + Slog.d(TAG, "getSapAutoChannelSelection"); + OperChanResp = mConnector.execute("softap", "qccmd", "get", "autochannel"); + + //Resp Pattern : 200 9 success autochannel=0 + final StringTokenizer tok = new StringTokenizer(OperChanResp.getMessage()); + tok.nextToken(); + String temp = (tok.hasMoreTokens()) ? tok.nextToken() : null; + if (temp != null) { + final StringTokenizer tok1 = new StringTokenizer(temp, "="); + String temp1 = (tok1.hasMoreTokens()) ? tok1.nextToken() : null; + String temp2 = (tok1.hasMoreTokens()) ? tok1.nextToken() : null; + if (temp2 != null) + autochannel = Integer.parseInt(temp2); + } + Slog.d(TAG, "getSapAutoChannelSelection--OperChanResp" + OperChanResp); + Slog.d(TAG, "softap qccmd get autochannel =" + autochannel); + return autochannel; + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException( + "Error communicating to native daemon to getSapOperatingChannel", e); + } + } + @Override public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java index 7773a261bea89..4a918a390d2ba 100644 --- a/wifi/java/android/net/wifi/WifiNative.java +++ b/wifi/java/android/net/wifi/WifiNative.java @@ -838,6 +838,27 @@ public List getSupportedChannels() { public native static boolean setMode(int mode); + /**Create P2P GO on the operating frequency*/ + public boolean p2pGroupAddOnSpecifiedFreq(int freq) { + return doBooleanCommand("P2P_GROUP_ADD" + " freq=" + freq); + } + + /**Set Channel preferrence eg., p2p_pref_chan=81:1,81:2,81:3,81:4,81:5,81:6*/ + public boolean setPreferredChannel(int startChannel, int endChannel) { + int i = 0; + if ((startChannel == 0) || (endChannel == 0)) return false; + StringBuffer strBuf = new StringBuffer(); + String command = "SET p2p_pref_chan "; + for (i = startChannel; i<=endChannel; i++) { + strBuf.append("81:" + i); + strBuf.append(","); + } + strBuf.deleteCharAt(strBuf.length() - 1); + command += strBuf; + Log.d(mTAG, "setPreferredChannel Command that goes to Supplicant is=" + command); + return doBooleanCommand(command) && doBooleanCommand("SAVE_CONFIG"); + } + /* Set the current mode of miracast operation. * 0 = disabled * 1 = operating as source diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index 24846ccb46d9d..e8c995f19879c 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -70,6 +70,9 @@ import android.util.LruCache; import android.text.TextUtils; +import android.util.Log; +import android.text.TextUtils; +import android.util.LruCache; import com.android.internal.R; import com.android.internal.app.IBatteryStats; import com.android.internal.util.AsyncChannel; @@ -101,6 +104,7 @@ */ public class WifiStateMachine extends StateMachine { + private static final String TAG = "WifiStateMachine"; private static final String NETWORKTYPE = "WIFI"; private static final boolean DBG = false; @@ -155,6 +159,8 @@ public class WifiStateMachine extends StateMachine { private PowerManager.WakeLock mSuspendWakeLock; private List mSupportedChannels; + private int startSafeChannel = 0; + private int endSafeChannel = 0; /** * Interval in milliseconds between polling for RSSI @@ -527,6 +533,8 @@ private class TetherStateChange { private static final int DRIVER_STOP_REQUEST = 0; private static final String ACTION_DELAYED_DRIVER_STOP = "com.android.server.WifiManager.action.DELAYED_DRIVER_STOP"; + private static final String ACTION_SAFE_WIFI_CHANNELS_CHANGED = + "qualcomm.intent.action.SAFE_WIFI_CHANNELS_CHANGED"; /** * Keep track of whether WIFI is running. @@ -612,7 +620,11 @@ public void onReceive(Context context, Intent intent) { } },new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED)); - mContext.registerReceiver( + IntentFilter filter = new IntentFilter(); + filter.addAction(ACTION_SAFE_WIFI_CHANNELS_CHANGED); + mContext.registerReceiver(WifiStateReceiver, filter); + + mContext.registerReceiver( new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -716,6 +728,32 @@ public void onReceive(Context context, Intent intent) { mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } + private BroadcastReceiver WifiStateReceiver = new BroadcastReceiver() { + + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals( + ACTION_SAFE_WIFI_CHANNELS_CHANGED)) { + startSafeChannel = intent.getIntExtra("start_safe_channel", -1); + endSafeChannel = intent.getIntExtra("end_safe_channel", -1); + Log.d(TAG, "Received WIFI_CHANNELS_CHANGED broadcast"); + int state = syncGetWifiApState(); + if (state == WIFI_AP_STATE_ENABLED) { + int autochannel = getSapAutoChannelSelection(); + Log.d(TAG,"autochannel=" + autochannel); + if (1 == autochannel){ + int currentChannel = getSapOperatingChannel(); + if (currentChannel >= 0 && + (currentChannel < startSafeChannel || + currentChannel > endSafeChannel)) { + Log.e(TAG, "Operating on restricted channel! Restart SAP"); + restartSoftApIfOn(); + } + } + } + } + } + }; + /********************************************************* * Methods exposed for public use ********************************************************/ @@ -803,6 +841,42 @@ public WifiConfiguration syncGetWifiApConfiguration() { return ret; } + /** + * Function to set Channel range. + */ + public void setChannelRange(int startchannel, int endchannel, int band) { + try { + Log.e(TAG, "setChannelRange"); + mNwService.setChannelRange(startchannel, endchannel, band); + } catch(Exception e) { + loge("Exception in setChannelRange"); + } + } + + /** + * Function to get SAP operating Channel + */ + public int getSapOperatingChannel() { + try { + return mNwService.getSapOperatingChannel(); + } catch(Exception e) { + loge("Exception in getSapOperatingChannel"); + return -1; + } + } + + /** + * Function to get Auto Channel selection + */ + public int getSapAutoChannelSelection() { + try { + return mNwService.getSapAutoChannelSelection(); + } catch (Exception e) { + loge("Exception in getSapOperatingChannel"); + return -1; + } + } + /** * TODO: doc */ @@ -1928,6 +2002,10 @@ public void run() { loge("Exception in softap start " + e); try { mNwService.stopAccessPoint(mInterfaceName); + if (startSafeChannel!=0) { + Log.e(TAG, "Calling setChannelRange ---startSoftApWithConfig()"); + setChannelRange(startSafeChannel, endSafeChannel, 0); + } mNwService.startAccessPoint(config, mInterfaceName); } catch (Exception e1) { loge("Exception in softap re-start " + e1); @@ -3622,6 +3700,10 @@ public void enter() { final WifiConfiguration config = (WifiConfiguration) message.obj; if (config == null) { + if (startSafeChannel!=0) { + Log.e(TAG, "Calling setChannelRange ---CMD_START_AP SoftApStartingState()"); + setChannelRange(startSafeChannel, endSafeChannel , 0); + } mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG); } else { mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config); @@ -3859,4 +3941,13 @@ private Message obtainMessageWithArg2(Message srcMsg) { msg.arg2 = srcMsg.arg2; return msg; } + + + private void restartSoftApIfOn() { + Log.e(TAG, "Disabling wifi ap"); + setHostApRunning(null, false); + Log.e(TAG, "Enabling wifi ap"); + setHostApRunning(null, true); + Log.e(TAG, "Restart softap Done"); + } } diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java index ca737f9e64d9c..76cae255ed3f2 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pGroup.java @@ -60,6 +60,9 @@ public class WifiP2pGroup implements Parcelable { /** The passphrase used for WPA2-PSK */ private String mPassphrase; + /** GO operating Frequency*/ + private int mGoOperFreq; + private String mInterface; /** The network id in the wpa_supplicant */ @@ -116,6 +119,7 @@ public WifiP2pGroup(String supplicantEvent) throws IllegalArgumentException { //freq and psk are unused right now //int freq = Integer.parseInt(match.group(2)); //String psk = match.group(3); + mGoOperFreq = Integer.parseInt(match.group(2)); mPassphrase = match.group(4); mOwner = new WifiP2pDevice(match.group(5)); if (match.group(6) != null) { @@ -228,6 +232,18 @@ public Collection getClientList() { return Collections.unmodifiableCollection(mClients); } + /** @hide */ + public int setGoOperatingFrequency(int GoOperFreq) { + return mGoOperFreq = GoOperFreq; + } + + /** @hide + * This is used to fetch the GO operating frequency + */ + public int getGoOperatingFrequency() { + return mGoOperFreq; + } + /** @hide */ public void setPassphrase(String passphrase) { mPassphrase = passphrase; @@ -290,6 +306,7 @@ public WifiP2pGroup(WifiP2pGroup source) { mPassphrase = source.getPassphrase(); mInterface = source.getInterface(); mNetId = source.getNetworkId(); + mGoOperFreq = source.getGoOperatingFrequency(); } } @@ -305,6 +322,7 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeString(mPassphrase); dest.writeString(mInterface); dest.writeInt(mNetId); + dest.writeInt(mGoOperFreq); } /** Implement the Parcelable interface */ @@ -322,6 +340,7 @@ public WifiP2pGroup createFromParcel(Parcel in) { group.setPassphrase(in.readString()); group.setInterface(in.readString()); group.setNetworkId(in.readInt()); + group.setGoOperatingFrequency(in.readInt()); return group; } diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java index aafa2eb0329b4..411061bd02c37 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -129,6 +129,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub { /* Idle time after a peer is gone when the group is torn down */ private static final int GROUP_IDLE_TIME_S = 10; + private static final String ACTION_SAFE_WIFI_CHANNELS_CHANGED = + "qualcomm.intent.action.SAFE_WIFI_CHANNELS_CHANGED"; private static final int BASE = Protocol.BASE_WIFI_P2P_SERVICE; @@ -185,6 +187,13 @@ public class WifiP2pService extends IWifiP2pManager.Stub { * is invoked */ private boolean mAutonomousGroup; + /**@hide*/ + public static boolean mIsWifiP2pEnabled = false; + + private int startSafeChannel = 0; + + private int endSafeChannel = 0; + /* Invitation to join an existing p2p group */ private boolean mJoinExistingGroup; @@ -314,6 +323,47 @@ public WifiP2pService(Context context) { mP2pStateMachine = new P2pStateMachine(TAG, mP2pSupported); mP2pStateMachine.start(); + // broadcasts + IntentFilter filter = new IntentFilter(); + filter.addAction(ACTION_SAFE_WIFI_CHANNELS_CHANGED); + mContext.registerReceiver(new WifiStateReceiver(), filter); + } + + private class WifiStateReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (intent.getAction().equals(ACTION_SAFE_WIFI_CHANNELS_CHANGED)) { + Slog.d(TAG, "Received WIFI_CHANNELS_CHANGED broadcast"); + startSafeChannel = intent.getIntExtra("start_safe_channel", -1); + endSafeChannel = intent.getIntExtra("end_safe_channel", -1); + if (mIsWifiP2pEnabled) { + Slog.d(TAG, "Set Preferred channel list for Non Auto GO"); + mP2pStateMachine.mWifiNative.setPreferredChannel( + startSafeChannel, endSafeChannel); + if (mP2pStateMachine.mWifiP2pInfo.groupFormed) { + int currentChannel = 0; + currentChannel = frequencyToChannel( + mP2pStateMachine.mGroup.getGoOperatingFrequency()); + Slog.d(TAG, "GO operating frequency=" + + mP2pStateMachine.mGroup.getGoOperatingFrequency()); + Slog.d(TAG, "current channel of P2P GO=" + currentChannel); + + if (currentChannel >= 0 && + (currentChannel < startSafeChannel || + currentChannel > endSafeChannel)) { + Slog.d(TAG, "P2P GO is operating on unsafe channel! Terminate!"); + mP2pStateMachine.mWifiNative.p2pGroupRemove( + mP2pStateMachine.mGroup.getInterface()); + if (mAutonomousGroup) + mP2pStateMachine.mWifiNative.p2pGroupAddOnSpecifiedFreq( + channelToFrequency(startSafeChannel)); + } + + } + } + } + } } public void connectivityServiceReady() { @@ -380,6 +430,32 @@ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(); } + /** + * Function to Convert frequency to Channel + */ + private int frequencyToChannel(int freq) { + /* see 802.11 17.3.8.3.2 and Annex J */ + if (freq == 2484) + return 14; + else if (freq < 2484) + return (freq - 2407) / 5; + else if (freq >= 4910 && freq <= 4980) + return (freq - 4000) / 5; + else + return (freq - 5000) / 5; + } + + /** + * Function to Convert Channel to frequency + */ + private int channelToFrequency(int chan) { + if (chan == 14) + return 2484; + else if (chan < 14) + return 2407 + chan * 5; + else + return 0; /* not supported */ + } /** * Handles interaction with WifiStateMachine @@ -749,6 +825,7 @@ public boolean processMessage(Message message) { if (DBG) logd(getName() + message.toString()); switch (message.what) { case WifiMonitor.SUP_DISCONNECTION_EVENT: + mIsWifiP2pEnabled = false; if (DBG) logd("p2p socket connection lost"); transitionTo(mP2pDisabledState); break; @@ -814,6 +891,7 @@ public boolean processMessage(Message message) { switch (message.what) { case WifiMonitor.SUP_CONNECTION_EVENT: if (DBG) logd("P2p socket connection successful"); + mIsWifiP2pEnabled = true; transitionTo(mInactiveState); break; case WifiMonitor.SUP_DISCONNECTION_EVENT: @@ -1145,7 +1223,13 @@ public boolean processMessage(Message message) { ret = mWifiNative.p2pGroupAdd(true); } } else { - ret = mWifiNative.p2pGroupAdd(false); + Slog.d(TAG, "startChannel while creating P2P Group=" + startSafeChannel); + if (startSafeChannel!=0) { + ret = mWifiNative.p2pGroupAddOnSpecifiedFreq( + channelToFrequency(startSafeChannel)); + } else { + ret = mWifiNative.p2pGroupAdd(false); + } } if (ret) { From 09670ae844975caeee0683d8fc47ed967dde0ec6 Mon Sep 17 00:00:00 2001 From: Deepthi Gowri Date: Tue, 6 Aug 2013 13:22:42 +0530 Subject: [PATCH 012/204] P2P: Set wifi preferred channels when the supplicant is started. Set wifi preferred channels when the supplicant is started, if there are any safe channels from the previous LTE event received from RIL. This is to ensure that p2p GO is always started on one safe channels. Change-Id: Ib0c36dbc4dfdec3721adb2f72d604158eeff9a87 CRs-Fixed: 523207 --- wifi/java/android/net/wifi/p2p/WifiP2pService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java index 411061bd02c37..f455ff3c28ed7 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -890,6 +890,9 @@ public boolean processMessage(Message message) { if (DBG) logd(getName() + message.toString()); switch (message.what) { case WifiMonitor.SUP_CONNECTION_EVENT: + if (startSafeChannel!=0) + mWifiNative.setPreferredChannel( + startSafeChannel, endSafeChannel); if (DBG) logd("P2p socket connection successful"); mIsWifiP2pEnabled = true; transitionTo(mInactiveState); From 433f4374d3c5e6ecf2dfc2b71efc8927e8fded22 Mon Sep 17 00:00:00 2001 From: Deepthi Gowri Date: Sun, 28 Jul 2013 16:35:40 +0530 Subject: [PATCH 013/204] wifi: Fix for connection between GO and p2p device When GO sends an invitation request to the p2p device without persistent profile, GO gets an invitation result=8 which means unknown group, when GO receives invitation result 8, its tries to remove persistent profile of the client but it will not be able find the profile so it does continue with sending the invitation so the connection fails. To address this, ignore if there are no persistent profiles found for the client and continue with sending the Invitation request to the client to make connection succesful connection. As GO has single profile saved unlike client which saves multiple profiles of GO. CRs-Fixed: 511282 Change-Id: I78f54d4bb2f0d603bc2170ec2c3ef55a91050236 --- wifi/java/android/net/wifi/p2p/WifiP2pService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java index f455ff3c28ed7..1e8182ed87b4f 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -1874,7 +1874,6 @@ public boolean processMessage(Message message) { mSavedPeerConfig.deviceAddress, false)) { // not found the client on the list loge("Already removed the client, ignore"); - break; } // try invitation. sendMessage(WifiP2pManager.CONNECT, mSavedPeerConfig); From d61b6b892dc6280121dd9ce75ddc279b7c0f7f3c Mon Sep 17 00:00:00 2001 From: Rashmi Ramanna Date: Fri, 30 Aug 2013 19:33:48 +0530 Subject: [PATCH 014/204] Show PIN on Peer device on receiving PIN display request. P2P provision discovery would request the peer to display a PIN. The PIN is displayed handling the request, the PIN need to be entered on keypad of requested peer device to achieve the connection. Change-Id: I8b6487681d78eb10c558983a08dec1ac8a8eee65 CRs-fixed: 382608 --- .../android/net/wifi/p2p/WifiP2pService.java | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java index 1e8182ed87b4f..3c652648b0cbe 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -1207,12 +1207,23 @@ public boolean processMessage(Message message) { break; case WifiMonitor.P2P_PROV_DISC_PBC_REQ_EVENT: case WifiMonitor.P2P_PROV_DISC_ENTER_PIN_EVENT: - case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: //We let the supplicant handle the provision discovery response //and wait instead for the GO_NEGOTIATION_REQUEST_EVENT. //Handling provision discovery and issuing a p2p_connect before //group negotiation comes through causes issues break; + case WifiMonitor.P2P_PROV_DISC_SHOW_PIN_EVENT: + WifiP2pProvDiscEvent provDisc = (WifiP2pProvDiscEvent) message.obj; + WifiP2pDevice device = provDisc.device; + if (device == null) { + Slog.d(TAG, "Device entry is null"); + break; + } + notifyP2pProvDiscShowPinRequest(provDisc.pin, device.deviceAddress); + mPeers.updateStatus(device.deviceAddress, WifiP2pDevice.INVITED); + sendPeersChangedBroadcast(); + transitionTo(mGroupNegotiationState); + break; case WifiP2pManager.CREATE_GROUP: mAutonomousGroup = true; int netId = message.arg1; @@ -2123,6 +2134,36 @@ private void notifyInvitationSent(String pin, String peerAddress) { dialog.show(); } + private void notifyP2pProvDiscShowPinRequest(String pin, String peerAddress) { + Resources r = Resources.getSystem(); + final String tempDevAddress = peerAddress; + final String tempPin = pin; + + final View textEntryView = LayoutInflater.from(mContext) + .inflate(R.layout.wifi_p2p_dialog, null); + + ViewGroup group = (ViewGroup) textEntryView.findViewById(R.id.info); + addRowToDialog(group, R.string.wifi_p2p_to_message, getDeviceName(peerAddress)); + addRowToDialog(group, R.string.wifi_p2p_show_pin_message, pin); + + AlertDialog dialog = new AlertDialog.Builder(mContext) + .setTitle(r.getString(R.string.wifi_p2p_invitation_sent_title)) + .setView(textEntryView) + .setPositiveButton(r.getString(R.string.accept), new OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + mSavedPeerConfig = new WifiP2pConfig(); + mSavedPeerConfig.deviceAddress = tempDevAddress; + mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY; + mSavedPeerConfig.wps.pin = tempPin; + mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP); + } + }) + .setCancelable(false) + .create(); + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + dialog.show(); + } + private void notifyInvitationReceived() { Resources r = Resources.getSystem(); final WpsInfo wps = mSavedPeerConfig.wps; From 7446927460b4f96714736bb13f234d39b4d35b34 Mon Sep 17 00:00:00 2001 From: Deepthi Gowri Date: Mon, 12 Aug 2013 11:49:01 +0530 Subject: [PATCH 015/204] P2P: Fix for GO inviting a p2p device. A p2p device on an invitation request from the peer invokes p2p_peer command to know if the peer is a p2p device / GO. Due to the cached entries there would be a possibility of not getting the updated information, ending up in the wrong negotiation with the invited peer. Thus do not rely on p2p_peer command, rather assume that the peer is a GO on an invitation request, provided there is no persistent network configured. Change-Id: Ic70c4147d8b34bcddf4bf70811a5aeb4ea0650bc CRs-Fixed: 486437 Conflicts: wifi/java/android/net/wifi/p2p/WifiP2pService.java --- wifi/java/android/net/wifi/p2p/WifiP2pService.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java index 3c652648b0cbe..1374c32e114b1 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -197,6 +197,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub { /* Invitation to join an existing p2p group */ private boolean mJoinExistingGroup; + private boolean mIsInvite = false; + /* Track whether we are in p2p discovery. This is used to avoid sending duplicate * broadcasts */ @@ -1174,6 +1176,7 @@ public boolean processMessage(Message message) { case WifiMonitor.P2P_INVITATION_RECEIVED_EVENT: WifiP2pGroup group = (WifiP2pGroup) message.obj; WifiP2pDevice owner = group.getOwner(); + mIsInvite = true; if (owner == null) { loge("Ignored invitation from null owner"); @@ -2344,15 +2347,24 @@ private WifiP2pDevice fetchCurrentDeviceDetails(WifiP2pConfig config) { * @param config for the peer */ private void p2pConnectWithPinDisplay(WifiP2pConfig config) { + boolean join = false; WifiP2pDevice dev = fetchCurrentDeviceDetails(config); - String pin = mWifiNative.p2pConnect(config, dev.isGroupOwner()); + if (mIsInvite) { + join = true; + } + else { + join = dev.isGroupOwner(); + } + + String pin = mWifiNative.p2pConnect(config, join); try { Integer.parseInt(pin); notifyInvitationSent(pin, config.deviceAddress); } catch (NumberFormatException ignore) { // do nothing if p2pConnect did not return a pin } + mIsInvite = false; } /** From ba4aa762bc80068f1c78e81106f98734038b6a8b Mon Sep 17 00:00:00 2001 From: Deepthi Gowri Date: Sun, 15 Sep 2013 23:31:04 +0530 Subject: [PATCH 016/204] P2P: Do not restart SAP/P2P Go if its operating in 5G. In case of LTE Coex since RIL always passes 2.4G channels, if the SAP or P2P Go are operating on 5G channels when LTE is camped, no need to restart SAP or P2P GO. Change-Id: I5b0b5452a94bcbc0beeb44b25c34daf9e17ee482 CRs-Fixed: 531439 --- wifi/java/android/net/wifi/WifiStateMachine.java | 8 ++++++-- wifi/java/android/net/wifi/p2p/WifiP2pService.java | 12 ++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index e8c995f19879c..d2fde34884339 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -745,8 +745,12 @@ public void onReceive(Context context, Intent intent) { if (currentChannel >= 0 && (currentChannel < startSafeChannel || currentChannel > endSafeChannel)) { - Log.e(TAG, "Operating on restricted channel! Restart SAP"); - restartSoftApIfOn(); + //currently RIL passes only 2.4G channels so if the current operating + // channel is 5G channel, do not restart SAP. + if (currentChannel >= 1 && currentChannel <=14) { + Log.e(TAG, "Operating on restricted channel! Restart SAP"); + restartSoftApIfOn(); + } } } } diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java index 1374c32e114b1..a444f50610cd2 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -354,12 +354,16 @@ public void onReceive(Context context, Intent intent) { if (currentChannel >= 0 && (currentChannel < startSafeChannel || currentChannel > endSafeChannel)) { - Slog.d(TAG, "P2P GO is operating on unsafe channel! Terminate!"); - mP2pStateMachine.mWifiNative.p2pGroupRemove( + //currently RIL passes only 2.4G channels so if the current operating + //channel is 5G channel, do not restart P2P GO. + if (currentChannel >= 1 && currentChannel <=14) { + Slog.d(TAG, "P2P GO is operating on unsafe channel! Terminate!"); + mP2pStateMachine.mWifiNative.p2pGroupRemove( mP2pStateMachine.mGroup.getInterface()); - if (mAutonomousGroup) - mP2pStateMachine.mWifiNative.p2pGroupAddOnSpecifiedFreq( + if (mAutonomousGroup) + mP2pStateMachine.mWifiNative.p2pGroupAddOnSpecifiedFreq( channelToFrequency(startSafeChannel)); + } } } From 5693ba41e43a1ac6c47c2cfb53d667fa000a270a Mon Sep 17 00:00:00 2001 From: Mahesh A Saptasagar Date: Mon, 16 Sep 2013 14:56:55 +0530 Subject: [PATCH 017/204] p2p: Fix for discovery failure until AP is connected in WFD client. When station is connecting to AP i.e wifi state is either connecting or obtaing ip address, Wi-Fi state machine will send BLOCK_DISCOVERY event to P2P service manager and discovery is postponed until DHCP success/failure. During this if we receive DISCOVER_PEERS command then p2p service manager will return discovery failure because "mDiscoveryPostponed" variable is not getting updated properly due to improper condition checking. To mitigate this issue modified the conditions to update the variable "mDiscoveryPostponed". CRs-Fixed: 532138 Change-Id: Ie92a42b17d264cfca5ec2af2dfb4db542deddaac --- .../android/net/wifi/p2p/WifiP2pService.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java index a444f50610cd2..9e27a9984a188 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -975,15 +975,11 @@ public boolean processMessage(Message message) { boolean blocked = (message.arg1 == ENABLED ? true : false); if (mDiscoveryBlocked == blocked) break; mDiscoveryBlocked = blocked; - if (blocked && mDiscoveryStarted) { - mWifiNative.p2pStopFind(); - mDiscoveryPostponed = true; - } - if (!blocked && mDiscoveryPostponed) { - mDiscoveryPostponed = false; - mWifiNative.p2pFind(DISCOVER_TIMEOUT_S); - } if (blocked) { + if (mDiscoveryStarted) { + mWifiNative.p2pStopFind(); + } + mDiscoveryPostponed = true; try { StateMachine m = (StateMachine)message.obj; m.sendMessage(message.arg2); @@ -991,12 +987,17 @@ public boolean processMessage(Message message) { loge("unable to send BLOCK_DISCOVERY response: " + e); } } + if (!blocked && mDiscoveryPostponed) { + mDiscoveryPostponed = false; + mWifiNative.p2pFind(DISCOVER_TIMEOUT_S); + } break; case WifiP2pManager.DISCOVER_PEERS: if (mDiscoveryBlocked) { - replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, - WifiP2pManager.BUSY); - break; + /* do not send discovery failure to apps. + since discovery is postponed and not failed */ + loge("P2P_FIND is deffered"); + break; } // do not send service discovery request while normal find operation. clearSupplicantServiceRequest(); From 120318de7d90a9132a7c27a84177e41537fefd84 Mon Sep 17 00:00:00 2001 From: Amar Singhal Date: Fri, 2 Aug 2013 11:11:08 -0700 Subject: [PATCH 018/204] Add RegulatoryObserver to framework base services RegulatoryObserver will catch country code change uevent and invoke crda. Change-Id: I24e3a3d5a5f7c533e018b7cdbdf87998a40a89c1 --- .../android/server/RegulatoryObserver.java | 135 ++++++++++++++++++ .../java/com/android/server/SystemServer.java | 9 ++ 2 files changed, 144 insertions(+) create mode 100644 services/java/com/android/server/RegulatoryObserver.java diff --git a/services/java/com/android/server/RegulatoryObserver.java b/services/java/com/android/server/RegulatoryObserver.java new file mode 100644 index 0000000000000..c4fb9ca51351d --- /dev/null +++ b/services/java/com/android/server/RegulatoryObserver.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.os.UEventObserver; +import android.os.SystemProperties; +import android.provider.Settings; +import android.util.Log; +import android.util.Slog; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.BufferedReader; +import java.io.InputStreamReader; + +/** + *

RegulatoryObserver monitors for country code change. + */ +class RegulatoryObserver extends UEventObserver { + private static final String TAG = RegulatoryObserver.class.getSimpleName(); + + private static final String REGULATORY_UEVENT_MATCH = "MODALIAS=platform:regulatory"; + private static final String UEVENT_FILE = "/sys/devices/platform/regulatory.0/uevent"; + + private String mCountryKeyword = "COUNTRY="; + private String mCountryCode; + private static final int MSG_COUNTRY_CODE = 0; + + private final Context mContext; + + public RegulatoryObserver(Context context) { + mContext = context; + init(); + startObserving(REGULATORY_UEVENT_MATCH); + } + + @Override + public void onUEvent(UEventObserver.UEvent event) { + Slog.v(TAG, "uevent:\n" + event.toString()); + synchronized (this) { + try { + mCountryCode = event.get("COUNTRY"); + Slog.v(TAG, "Regulatory Country Code:" + mCountryCode); + run_crda(); + } catch (NumberFormatException e) { + Slog.e(TAG, "Could not parse country code from event " + event); + } + } + } + + private final void init() { + try { + Slog.v(TAG, "RegulatoryObserver init."); + // Read the regulatory uevent file to check if any pending + // uevent before we start observing + BufferedReader uevent_buf = new BufferedReader(new FileReader(UEVENT_FILE)); + String line; + while (((line = uevent_buf.readLine()) != null) + && (line.length() != 0)) { + String[] event_string = line.split("="); + String key = event_string[0]; + String value = event_string[1]; + if (key.equals("COUNTRY")) { + // If it has COUNTRY code, it's a pending request before + // RegulatoryObserver started. Very likely it's from + // CFG80211 which is built in to kernel. + mCountryCode = value; + run_crda(); + } + } + } catch (Exception e) { + Slog.e(TAG, "This kernel may not have CRDA support." , e); + } + } + + private final void run_crda() { + try { + if (mCountryCode != null) { + // setprop wlan.crda.country then start wifi-crda service + SystemProperties.set("wlan.crda.country", mCountryCode); + SystemProperties.set("ctl.start", "wifi-crda"); + Slog.v(TAG, "Start wifi-crda service to run crda."); + Slog.v(TAG, "Country Code is " + mCountryCode); + // Broadcast intent is allowed after boot is completed + if ("1".equals(SystemProperties.get("sys.boot_completed"))) { + mHandler.sendEmptyMessage(MSG_COUNTRY_CODE); + Slog.v(TAG, "Send broadcast country code message."); + } + } + } catch (Exception e) { + Slog.e(TAG, "Failed to start wifi-crda service to run crda." , e); + } + } + + private final Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_COUNTRY_CODE: + synchronized (this) { + Slog.i(TAG, "Broadcast intent for crda country code: " + mCountryCode); + Intent broadcastIntent = new Intent(); + broadcastIntent.setAction("crda.custom.intent.action.COUNTRY_CODE"); + mContext.sendBroadcast(broadcastIntent); + } + break; + } + } + }; +} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 72e8f125ad54a..63d5108503b03 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -167,6 +167,7 @@ public void run() { BluetoothManagerService bluetooth = null; DockObserver dock = null; RotationSwitchObserver rotateSwitch = null; + RegulatoryObserver regulatory = null; UsbService usb = null; SerialService serial = null; TwilightService twilight = null; @@ -509,6 +510,14 @@ public void run() { reportWtf("starting NetworkPolicy Service", e); } + try { + Slog.i(TAG, "Regulatory Observer"); + // Listen for country code changes + regulatory = new RegulatoryObserver(context); + } catch (Throwable e) { + reportWtf("starting RegulatoryObserver", e); + } + try { Slog.i(TAG, "Wi-Fi P2pService"); wifiP2p = new WifiP2pService(context); From b1aebcd8f3ff8042061d03c5ae8e532f93f6b83b Mon Sep 17 00:00:00 2001 From: nagarw Date: Wed, 18 Sep 2013 16:52:01 +0530 Subject: [PATCH 019/204] frameworks/base/: Fix black wallpaper issue when home pressed. In the specified usecase, there is a completely new set of windows that appear on the screen during rotation. And the existing code in the framework ignores the drawstate of the hidden windows. Wait till the drawState is ready for the hidden windows also. CRs-Fixed: 521758 Change-Id: Ibd96502059c84210ad84ecb03aac5eca28f3c9fe --- services/java/com/android/server/wm/WindowStateAnimator.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java index c07174baf4c37..8082e297b12fc 100644 --- a/services/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/java/com/android/server/wm/WindowStateAnimator.java @@ -1233,7 +1233,9 @@ public void prepareSurfaceLocked(final boolean recoveringMemory) { // introduce a potential glitch if the window // becomes unhidden before it has drawn for the // new orientation. - if (w.mOrientationChanging) { + if (!w.isDrawnLw()) { + displayed = true; + } else if (w.mOrientationChanging) { w.mOrientationChanging = false; if (DEBUG_ORIENTATION) Slog.v(TAG, "Orientation change skips hidden " + w); From 8841e1c8398060fabe18c22983c585b33c010e09 Mon Sep 17 00:00:00 2001 From: MatoDroid Date: Mon, 30 Sep 2013 18:38:50 +0200 Subject: [PATCH 020/204] core: SK translations Change-Id: Id9ec746c867f6379f05913e2a9f02c5ce5bfa7cc --- core/res/res/values-sk/cm_strings.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/res/res/values-sk/cm_strings.xml b/core/res/res/values-sk/cm_strings.xml index 3278a7be23618..a1eb4ef6be7c4 100644 --- a/core/res/res/values-sk/cm_strings.xml +++ b/core/res/res/values-sk/cm_strings.xml @@ -16,14 +16,14 @@ Predvolený - V práci + Práca Doma Tichý - Nočný + Noc Telefón Kalendár Gmail - Email + E-mail SMS Iný Reštart tabletu @@ -52,8 +52,8 @@ Aplikácia bola ukončená Reštartovať Profil - Otočenie obrazovky odomknuté - Otočenie obrazovky uzamknuté + Otáčanie obrazovky odomknuté + Otáčanie obrazovky uzamknuté Aplikácia %s nie je nainštalovaná povoliť alebo zakázať ochranu súkromia Umožňuje aplikácii určiť, či má byť iná aplikácia spustená s ochranou súkromia. Keď je aplikácia spustená s ochranou súkromia, nemá umožnený prístup k osobným údajom ako sú kontakty, denníky hovorov, alebo správy. @@ -69,7 +69,7 @@ Prepnúť stav zabezpečenia SELinux. vynútiť MMAC Prepnúť stav zabezpečenia MMAC. - poslať falošné SMS správy + posielať falošné SMS správy Povolí aplikácii odosielať falošné SMS správy. Toto povolenie umožňuje aplikácii posielať SMS do dôveryhodných aplikácií. Škodlivé aplikácie môžu posielať správy nepretržite, blokovať oznamovací systém zariadenia a vyrušovať užívateľa. Nie je dostupné žiadne vymeniteľné médium\u2026 From d917f7f4f36c8b75236b834ed135575e319ccecc Mon Sep 17 00:00:00 2001 From: MatoDroid Date: Wed, 9 Oct 2013 17:26:41 +0200 Subject: [PATCH 021/204] SystemUI: SK translations Change-Id: If09132206d7f7da24154abf2d24bf195d890f86f --- packages/SystemUI/res/values-sk/cm_strings.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/SystemUI/res/values-sk/cm_strings.xml b/packages/SystemUI/res/values-sk/cm_strings.xml index 70699067060ac..a97adb13e02a3 100644 --- a/packages/SystemUI/res/values-sk/cm_strings.xml +++ b/packages/SystemUI/res/values-sk/cm_strings.xml @@ -24,7 +24,7 @@ Časový limit obrazovky bol nastavený na: %1$d %2$s GPS GPS vyp. - Spánok + Prejsť do spánku Zvuk zap. Zvuk vyp. Vibrácie zap. @@ -56,6 +56,8 @@ Normálna Vyberte akciu na priradenie Fotoaparát + Zakázané + Povolené Nemožno sa pripojiť k fotoaparátu Tlačidlo Domov Tlačidlo Nedávne From a9467687dfd1f9a0a3679d314196016e34c00875 Mon Sep 17 00:00:00 2001 From: Bing-Hua Wang Date: Thu, 10 Oct 2013 00:09:54 +0800 Subject: [PATCH 022/204] SystemUI: zh-rTW translations Change-Id: I94bd89027e97b6dcc48d29181a8145452bb96f4c --- .../SystemUI/res/values-zh-rTW/cm_strings.xml | 74 ++++++++++--------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/packages/SystemUI/res/values-zh-rTW/cm_strings.xml b/packages/SystemUI/res/values-zh-rTW/cm_strings.xml index 9ba1dd26a92cc..2a373af9cdc38 100644 --- a/packages/SystemUI/res/values-zh-rTW/cm_strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/cm_strings.xml @@ -1,5 +1,5 @@ - - 預設 工作 @@ -26,12 +25,12 @@ 電子郵件 簡訊 其他 - 重新啟動平板 + 重新啟動平板電腦 重新啟動手機 - 螢幕截圖 + 螢幕擷取 擴展桌面 啟用 - 禁用 + 停用 重新啟動 Recovery Bootloader @@ -39,22 +38,25 @@ Fastboot Download 正在重新啟動\u2026 - 您的平板將會重新啟動。 + 您的平板電腦將會重新啟動。 您的手機將會重新啟動。 防止使用電源鍵 - 允許應用程式覆蓋電源鍵的功能。 - 控制電台接收器 - 允許應用程式控制電台接收器。 - 控制電台發送器 - 允許應用程式控制電台發送器。 - 放電中, %d%% - 底座SD卡 + 允許應用程式覆寫電源鍵的功能。 + 控制 FM 接收器 + 允許應用程式控制 FM 接收器。 + 控制 FM 發送器 + 允許應用程式控制 FM 發送器。 + 傳送模擬簡訊 + 允許應用程式傳送模擬簡訊,這會允許應用程式傳送簡訊給信任的應用程式。惡意應用程式可能會不斷地傳送訊息,妨礙裝置的通知系統以及干擾使用者。 + 非充電中,%d%% + 沒有可移除的媒體\u2026 + 座架 SD 卡 應用程式已終止 重新啟動 設定檔 顯示旋轉已解鎖 顯示旋轉已鎖定 - %s未安裝 + 未安裝 %s \u00C0\u00C1\u00C2\u00C4\u00C6\u00C3\u00C5\u0104\u0100 \u00C7\u0106\u010C \u010E @@ -109,17 +111,17 @@ \u2264\u00ab\u2039 \u2265\u00bb\u203a 啟用或停用隱私守衛 - 允許此應用程式向另一個與隱私守衛一起運行的應用程式作出更改。當應用程式與隱私守衛一起運行時,應用程式將無法存取個人資料,如聯絡人,通話記錄,或簡訊。 - 隱私守衛啟用中 + 允許應用程式變更其他應用程式執行時是否啟用隱私守衛。當應用程式執行時啟用了隱私守衛,應用程式將無法存取個人資料,例如聯絡人、通話記錄、或訊息。 + 隱私守衛作用中 %1$s 將無法存取個人資料 設定檔 取消應用程式通知 - 允許此應用程式取消其他應用程式建立的通知。 - 攔截外撥簡訊 - 允許此應用程式攔截外撥簡訊。惡意應用程式可能會利用此去防止發送外撥簡訊。 - 強制執行 SELinux - 切換 SELinux 政策強制執行模式或許可模式。 - 強制執行 MMAC - 切換 MMAC 政策強制執行模式或許可模式。 + 允許應用程式取消其他應用程式建立的通知。 + 攔截送出簡訊 + 允許應用程式攔截送出簡訊。惡意應用程式可能會利用此去阻止送出簡訊。 + 執行 SELinux + 切換 SELinux 政策執行模式或許可模式。 + 執行 MMAC + 切換 MMAC 政策執行模式或許可模式。 From 98d10e81f9c5f2e686ee7eb308ba5c78d4ab8922 Mon Sep 17 00:00:00 2001 From: dhacker29 Date: Wed, 16 Oct 2013 20:51:28 -0500 Subject: [PATCH 025/204] IPV6 tethering: Check info for null before removeUpstreamV6Interface When tethering on dual stack networks such as verizon wireless and sending or recieving MMS you get an null pointer exception and hard reboot. It starts to go wrong here: 10-14 19:11:51.375: E/Mms/smil(28035): Failed to parse SMIL document. 10-14 19:11:51.375: E/Mms/smil(28035): org.xml.sax.SAXParseException: expected start tag notEND_DOCUMENT null@1:1 in java.io.InputStreamReader @4192ada0 And then: 10-14 19:11:55.559: E/AndroidRuntime(23125): java.lang.NullPointerException 10-14 19:11:55.559: E/AndroidRuntime(23125): at com.android.server. connectivity.Tethering$TetherMasterSM$TetherModeAliveState.processMessage (Tethering.java:1573) Which is line 1573 of: https://github.com/CyanogenMod/android_frameworks_base/blob/cm-10.2/services/java/com/android/server/connectivity/Tethering.java#L1573 CMD_UPSTREAM_CHANGED's message.obj can be null (line 776). Change-Id: I13d531d398f2e33a828c6e81f25f4b2a27518d34 --- .../android/server/connectivity/Tethering.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java index 790f19dfd0698..825327654f06c 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/java/com/android/server/connectivity/Tethering.java @@ -1570,14 +1570,16 @@ public boolean processMessage(Message message) { NetworkInfo info = (NetworkInfo) message.obj; mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; chooseUpstreamType(mTryCell); - if (!info.isConnected()) { - IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); - IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); - try { - LinkProperties props = cm.getLinkProperties(info.getType()); - removeUpstreamV6Interface(props.getInterfaceName()); - } catch(Exception e) { - Log.e(TAG, "Exception querying ConnectivityManager", e); + if (info != null) { + if (!info.isConnected()) { + IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); + IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); + try { + LinkProperties props = cm.getLinkProperties(info.getType()); + removeUpstreamV6Interface(props.getInterfaceName()); + } catch(Exception e) { + Log.e(TAG, "Exception querying ConnectivityManager", e); + } } } mTryCell = !mTryCell; From e4fe13562a0a0b2231d010c24a4a2003feebd5cb Mon Sep 17 00:00:00 2001 From: SanthoshHE Date: Tue, 30 Jul 2013 12:35:17 +0530 Subject: [PATCH 026/204] Camera: Video HDR Feature Integration. Added framework support for camera applications to query supported video HDR modes and set the required mode. Change-Id: Ie318e586838a2f035e59e30fa51af35b52f7c886 --- core/java/android/hardware/Camera.java | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 7bf524662487d..54cdac923f7ec 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -4075,6 +4075,7 @@ private boolean same(String s1, String s2) { private static final String KEY_QC_ZSL = "zsl"; private static final String KEY_QC_CAMERA_MODE = "camera-mode"; private static final String KEY_QC_VIDEO_HIGH_FRAME_RATE = "video-hfr"; + private static final String KEY_QC_VIDEO_HDR = "video-hdr"; /** @hide * KEY_QC_AE_BRACKET_HDR **/ @@ -4377,6 +4378,17 @@ public List getSupportedZSLModes() { return split(str); } + /** @hide + * Gets the supported Video HDR modes. + * + * @return a List of Video HDR_OFF/OFF string constants. null if + * Video HDR mode setting is not supported. + */ + public List getSupportedVideoHDRModes() { + String str = get(KEY_QC_VIDEO_HDR + SUPPORTED_VALUES_SUFFIX); + return split(str); + } + /** @hide * Gets the supported HFR modes. * @@ -4853,6 +4865,24 @@ public void setVideoHighFrameRate(String hfr) { set(KEY_QC_VIDEO_HIGH_FRAME_RATE, hfr); } + /** @hide + * Gets the current Video HDR Mode. + * + * @return Video HDR mode value + */ + public String getVideoHDRMode() { + return get(KEY_QC_VIDEO_HDR); + } + + /** @hide + * Sets the current Video HDR Mode. + * + * @return null + */ + public void setVideoHDRMode(String videohdr) { + set(KEY_QC_VIDEO_HDR, videohdr); + } + /** @hide * Gets the current DENOISE setting. * From 46820e10a3748dd1e5e5f3f9eea33e13be3ae288 Mon Sep 17 00:00:00 2001 From: Emilian Peev Date: Mon, 12 Aug 2013 16:02:50 +0300 Subject: [PATCH 027/204] Camera: Adds support for meta data callbacks - This change adds a new type of callback that will be called when there are pending meta data notifications. Change-Id: I84f5cbafe4f023c7b0efa9ec8620756b0eaa428d --- core/java/android/hardware/Camera.java | 15 +++++++-------- core/jni/android_hardware_Camera.cpp | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 54cdac923f7ec..b8ba2c3f823b6 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -869,7 +869,7 @@ public void handleMessage(Message msg) { case CAMERA_MSG_META_DATA: if (mCameraMetaDataCallback != null) { - mCameraMetaDataCallback.onCameraMetaData((int[])msg.obj, mCamera); + mCameraMetaDataCallback.onCameraMetaData((byte[])msg.obj, mCamera); } return; /* ### QC ADD-ONS: END */ @@ -1620,25 +1620,24 @@ public interface CameraMetaDataCallback { /** * Callback for when camera meta data is available. * - * @param data a int array of the camera meta data + * @param data a byte array of the camera meta data * @param camera the Camera service object */ - void onCameraMetaData(int[] data, Camera camera); + void onCameraMetaData(byte[] data, Camera camera); }; /** @hide - * Set camera face detection mode and registers a callback function to run. + * Set camera meta data and registers a callback function to run. * Only valid after startPreview() has been called. * * @param cb the callback to run */ - //TBD - public final void setFaceDetectionCb(CameraMetaDataCallback cb) + public final void setMetadataCb(CameraMetaDataCallback cb) { mCameraMetaDataCallback = cb; - native_setFaceDetectionCb(cb!=null); + native_setMetadataCb(cb!=null); } - private native final void native_setFaceDetectionCb(boolean mode); + private native final void native_setMetadataCb(boolean mode); /** @hide * Set camera face detection command to send meta data. diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index 450b785cdf2f8..b3ddd874d25bb 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -666,6 +666,24 @@ static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject t context->setCallbackMode(env, installed, manualBuffer); } +static void android_hardware_Camera_setMetadataCb(JNIEnv *env, jobject thiz, jboolean mode) +{ + ALOGV("setMetadataCb: mode:%d", (int)mode); + JNICameraContext* context; + status_t rc; + sp camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + if(mode == true) + rc = camera->sendCommand(CAMERA_CMD_METADATA_ON, 0, 0); + else + rc = camera->sendCommand(CAMERA_CMD_METADATA_OFF, 0, 0); + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "set metadata mode failed"); + } +} + static void android_hardware_Camera_addCallbackBuffer(JNIEnv *env, jobject thiz, jbyteArray bytes, int msgType) { ALOGV("addCallbackBuffer: 0x%x", msgType); @@ -958,6 +976,9 @@ static JNINativeMethod camMethods[] = { { "native_setHistogramMode", "(Z)V", (void *)android_hardware_Camera_setHistogramMode }, + { "native_setMetadataCb", + "(Z)V", + (void *)android_hardware_Camera_setMetadataCb }, { "native_sendHistogramData", "()V", (void *)android_hardware_Camera_sendHistogramData }, From f274625e1de909264f72079c0472fe440ed4a140 Mon Sep 17 00:00:00 2001 From: Ashwini Rao Date: Thu, 16 Feb 2012 14:20:56 -0800 Subject: [PATCH 028/204] Frameworks: Enhance face detection Add support for facial processing features: smile detection, gaze detection and blink detection Change-Id: Ic186ff0658e755a8b5287cffa1dd58d9eafebc9a --- core/java/android/hardware/Camera.java | 17 ++++ core/jni/android_hardware_Camera.cpp | 131 +++++++++++++++++++++++-- 2 files changed, 142 insertions(+), 6 deletions(-) diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index b8ba2c3f823b6..71b8401aa22bb 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -1481,6 +1481,23 @@ public Face() { * as a set. Either they are all valid, or none of them are. */ public Point mouth = null; + + /** + * {@hide} + */ + public int smileDegree = 0; + /** + * {@hide} + */ + public int smileScore = 0; + /** + * {@hide} + */ + public int blinkDetected = 0; + /** + * {@hide} + */ + public int faceRecognised = 0; } // Error codes match the enum in include/ui/Camera.h diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index b3ddd874d25bb..aa4b4aab49149 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -49,6 +49,25 @@ struct fields_t { jmethodID post_event; jmethodID rect_constructor; jmethodID face_constructor; + jfieldID face_id; + jfieldID face_leftEye; + jfieldID face_rightEye; + jfieldID face_mouth; + jfieldID face_sm_degree; + jfieldID face_sm_score; + jfieldID face_blink_detected; + jfieldID face_gaze_angle; + jfieldID face_updown_dir; + jfieldID face_leftright_dir; + jfieldID face_roll_dir; + jfieldID face_leye_blink; + jfieldID face_reye_blink; + jfieldID face_left_right_gaze; + jfieldID face_top_bottom_gaze; + jfieldID face_recognised; + jfieldID point_x; + jfieldID point_y; + jmethodID point_constructor; }; static fields_t fields; @@ -82,6 +101,8 @@ class JNICameraContext: public CameraListener sp mCamera; // strong reference to native object jclass mFaceClass; // strong reference to Face class jclass mRectClass; // strong reference to Rect class + jclass mPointClass; // strong reference to Point class + bool mIsQcFace; Mutex mLock; /* @@ -132,12 +153,22 @@ JNICameraContext::JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, mCameraJClass = (jclass)env->NewGlobalRef(clazz); mCamera = camera; - jclass faceClazz = env->FindClass("android/hardware/Camera$Face"); - mFaceClass = (jclass) env->NewGlobalRef(faceClazz); + jclass qcfaceClazz = env->FindClass("org/codeaurora/camera/QCFace"); + if (NULL != qcfaceClazz) { + mFaceClass = (jclass) env->NewGlobalRef(qcfaceClazz); + mIsQcFace = true; + } else { + jclass faceClazz = env->FindClass("android/hardware/Camera$Face"); + mFaceClass = (jclass) env->NewGlobalRef(faceClazz); + mIsQcFace = false; + } jclass rectClazz = env->FindClass("android/graphics/Rect"); mRectClass = (jclass) env->NewGlobalRef(rectClazz); + jclass pointClazz = env->FindClass("android/graphics/Point"); + mPointClass = (jclass) env->NewGlobalRef(pointClazz); + mManualBufferMode = false; mManualCameraCallbackSet = false; } @@ -164,6 +195,10 @@ void JNICameraContext::release() env->DeleteGlobalRef(mRectClass); mRectClass = NULL; } + if (mPointClass != NULL) { + env->DeleteGlobalRef(mPointClass); + mPointClass = NULL; + } clearCallbackBuffers_l(env); mCamera.clear(); } @@ -346,12 +381,47 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m env->SetIntField(rect, fields.rect_top, metadata->faces[i].rect[1]); env->SetIntField(rect, fields.rect_right, metadata->faces[i].rect[2]); env->SetIntField(rect, fields.rect_bottom, metadata->faces[i].rect[3]); - env->SetObjectField(face, fields.face_rect, rect); env->SetIntField(face, fields.face_score, metadata->faces[i].score); + jobject point1 = env->NewObject(mPointClass, fields.point_constructor); + env->SetIntField(point1, fields.point_x, metadata->faces[i].left_eye[0]); + env->SetIntField(point1, fields.point_y, metadata->faces[i].left_eye[1]); + env->SetObjectField(face, fields.face_leftEye, point1); + + jobject point2 = env->NewObject(mPointClass, fields.point_constructor); + env->SetIntField(point2, fields.point_x, metadata->faces[i].right_eye[0]); + env->SetIntField(point2, fields.point_y, metadata->faces[i].right_eye[1]); + env->SetObjectField(face, fields.face_rightEye, point2); + + jobject point3 = env->NewObject(mPointClass, fields.point_constructor); + env->SetIntField(point3, fields.point_x, metadata->faces[i].mouth[0]); + env->SetIntField(point3, fields.point_y, metadata->faces[i].mouth[1]); + env->SetObjectField(face, fields.face_mouth, point3); + + env->SetIntField(face, fields.face_id, metadata->faces[i].id); + + if (mIsQcFace) { + env->SetIntField(face, fields.face_sm_degree, metadata->faces[i].smile_degree); + env->SetIntField(face, fields.face_sm_score, metadata->faces[i].smile_score); + env->SetIntField(face, fields.face_blink_detected, metadata->faces[i].blink_detected); + env->SetIntField(face, fields.face_recognised, metadata->faces[i].face_recognised); + env->SetIntField(face, fields.face_gaze_angle, metadata->faces[i].gaze_angle); + env->SetIntField(face, fields.face_updown_dir, metadata->faces[i].updown_dir); + env->SetIntField(face, fields.face_leftright_dir, metadata->faces[i].leftright_dir); + env->SetIntField(face, fields.face_roll_dir, metadata->faces[i].roll_dir); + env->SetIntField(face, fields.face_leye_blink, metadata->faces[i].leye_blink); + env->SetIntField(face, fields.face_reye_blink, metadata->faces[i].reye_blink); + env->SetIntField(face, fields.face_left_right_gaze, metadata->faces[i].left_right_gaze); + env->SetIntField(face, fields.face_top_bottom_gaze, metadata->faces[i].top_bottom_gaze); + } + env->DeleteLocalRef(face); env->DeleteLocalRef(rect); + + env->DeleteLocalRef(point1); + env->DeleteLocalRef(point2); + env->DeleteLocalRef(point3); } env->CallStaticVoidMethod(mCameraJClass, fields.post_event, mCameraJObjectWeak, msgType, 0, 0, obj); @@ -1061,12 +1131,46 @@ int register_android_hardware_Camera(JNIEnv *env) { "android/hardware/Camera$CameraInfo", "orientation", "I", &fields.orientation }, { "android/hardware/Camera$CameraInfo", "canDisableShutterSound", "Z", &fields.canDisableShutterSound }, - { "android/hardware/Camera$Face", "rect", "Landroid/graphics/Rect;", &fields.face_rect }, - { "android/hardware/Camera$Face", "score", "I", &fields.face_score }, { "android/graphics/Rect", "left", "I", &fields.rect_left }, { "android/graphics/Rect", "top", "I", &fields.rect_top }, { "android/graphics/Rect", "right", "I", &fields.rect_right }, { "android/graphics/Rect", "bottom", "I", &fields.rect_bottom }, + { "android/graphics/Point", "x", "I", &fields.point_x }, + { "android/graphics/Point", "y", "I", &fields.point_y }, + }; + + field facefields_to_find[] = { + { "android/hardware/Camera$Face", "rect", "Landroid/graphics/Rect;", &fields.face_rect }, + { "android/hardware/Camera$Face", "score", "I", &fields.face_score }, + { "android/hardware/Camera$Face", "id", "I", &fields.face_id }, + { "android/hardware/Camera$Face", "leftEye", "Landroid/graphics/Point;", &fields.face_leftEye }, + { "android/hardware/Camera$Face", "rightEye", "Landroid/graphics/Point;", &fields.face_rightEye }, + { "android/hardware/Camera$Face", "mouth", "Landroid/graphics/Point;", &fields.face_mouth }, + { "android/hardware/Camera$Face", "smileDegree", "I", &fields.face_sm_degree }, + { "android/hardware/Camera$Face", "smileScore", "I", &fields.face_sm_score }, + { "android/hardware/Camera$Face", "blinkDetected", "I", &fields.face_blink_detected }, + { "android/hardware/Camera$Face", "faceRecognised", "I", &fields.face_recognised }, + }; + + field qcfacefields_to_find[] = { + { "org/codeaurora/camera/QCFace", "rect", "Landroid/graphics/Rect;", &fields.face_rect }, + { "org/codeaurora/camera/QCFace", "score", "I", &fields.face_score }, + { "org/codeaurora/camera/QCFace", "id", "I", &fields.face_id }, + { "org/codeaurora/camera/QCFace", "leftEye", "Landroid/graphics/Point;", &fields.face_leftEye }, + { "org/codeaurora/camera/QCFace", "rightEye", "Landroid/graphics/Point;", &fields.face_rightEye }, + { "org/codeaurora/camera/QCFace", "mouth", "Landroid/graphics/Point;", &fields.face_mouth }, + { "org/codeaurora/camera/QCFace", "smileDegree", "I", &fields.face_sm_degree }, + { "org/codeaurora/camera/QCFace", "smileScore", "I", &fields.face_sm_score }, + { "org/codeaurora/camera/QCFace", "blinkDetected", "I", &fields.face_blink_detected }, + { "org/codeaurora/camera/QCFace", "faceRecognized", "I", &fields.face_recognised }, + { "org/codeaurora/camera/QCFace", "gazeAngle", "I", &fields.face_gaze_angle }, + { "org/codeaurora/camera/QCFace", "updownDir", "I", &fields.face_updown_dir }, + { "org/codeaurora/camera/QCFace", "leftrightDir", "I", &fields.face_leftright_dir }, + { "org/codeaurora/camera/QCFace", "rollDir", "I", &fields.face_roll_dir }, + { "org/codeaurora/camera/QCFace", "leyeBlink", "I", &fields.face_leye_blink }, + { "org/codeaurora/camera/QCFace", "reyeBlink", "I", &fields.face_reye_blink }, + { "org/codeaurora/camera/QCFace", "leftrightGaze", "I", &fields.face_left_right_gaze }, + { "org/codeaurora/camera/QCFace", "topbottomGaze", "I", &fields.face_top_bottom_gaze }, }; if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0) @@ -1087,13 +1191,28 @@ int register_android_hardware_Camera(JNIEnv *env) return -1; } + clazz = env->FindClass("android/graphics/Point"); + fields.point_constructor = env->GetMethodID(clazz, "", "()V"); + if (fields.point_constructor == NULL) { + ALOGE("Can't find android/graphics/Point.Point()"); + return -1; + } + + clazz = env->FindClass("org/codeaurora/camera/QCFace"); + if (NULL != clazz) { + fields.face_constructor = env->GetMethodID(clazz, "", "()V"); + if (find_fields(env, qcfacefields_to_find, NELEM(qcfacefields_to_find)) < 0) + return -1; + } else { clazz = env->FindClass("android/hardware/Camera$Face"); fields.face_constructor = env->GetMethodID(clazz, "", "()V"); if (fields.face_constructor == NULL) { ALOGE("Can't find android/hardware/Camera$Face.Face()"); return -1; + } + if (find_fields(env, facefields_to_find, NELEM(fields_to_find)) < 0) + return -1; } - // Register native functions return AndroidRuntime::registerNativeMethods(env, "android/hardware/Camera", camMethods, NELEM(camMethods)); From e0c114fb9f1d0bc7cf00c4c2da766690210d846b Mon Sep 17 00:00:00 2001 From: Ivan Evlogiev Date: Thu, 22 Aug 2013 15:28:47 +0300 Subject: [PATCH 029/204] Frameworks: QCFace framework added Add framework support for extended face detect Change-Id: I2a1c477ee6d11f2b9764966abbb85ede9100fe91 --- core/java/com/qualcomm/camera/QCFace.java | 203 ++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 core/java/com/qualcomm/camera/QCFace.java diff --git a/core/java/com/qualcomm/camera/QCFace.java b/core/java/com/qualcomm/camera/QCFace.java new file mode 100644 index 0000000000000..65bea7901cef1 --- /dev/null +++ b/core/java/com/qualcomm/camera/QCFace.java @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Copyright (C) 2012 The Android Open Source Project + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.codeaurora.camera; + +import android.hardware.Camera; + +import java.util.ArrayList; + +import android.os.Bundle; + +import android.os.SystemProperties; + +/** + * {@hide} Information about a Qaulcomm face identified through camera face + * detection. + * + *

+ * When face detection is used with a camera, the {@link FaceDetectionListener} + * returns a list of face objects for use in focusing and metering. + *

+ * + * @see FaceDetectionListener + */ +public class QCFace extends android.hardware.Camera.Face { + public QCFace() { + super(); + } + + private int smileDegree = 0; + private int smileScore = 0; + private int blinkDetected = 0; + private int faceRecognized = 0; + private int gazeAngle = 0; + private int updownDir = 0; + private int leftrightDir = 0; + private int rollDir = 0; + private int leyeBlink = 0; + private int reyeBlink = 0; + private int leftrightGaze = 0; + private int topbottomGaze = 0; + + private static final String STR_TRUE = "true"; + private static final String STR_FALSE = "false"; + private static final String STR_FACIAL_PROCESSING = "ro.qc.sdk.camera.facialproc"; + + /** + * The smilie degree for the detection of the face. + * + * @see #startFaceDetection() + */ + public int getSmileDegree() { + return smileDegree; + } + + /** + * The smilie score for the detection of the face. + * + * @see #startFaceDetection() + */ + public int getSmileScore() { + return smileScore; + } + + /** + * The smilie degree for the detection of the face. + * + * @see #startFaceDetection() + */ + public int getBlinkDetected() { + return blinkDetected; + } + + /** + * If face is recognized. + * + * @see #startFaceDetection() + */ + public int getFaceRecognized() { + return faceRecognized; + } + + /** + * The gaze angle for the detected face. + * + * @see #startFaceDetection() + */ + public int getGazeAngle() { + return gazeAngle; + } + + /** + * The up down direction for the detected face. + * + * @see #startFaceDetection() + */ + public int getUpDownDirection() { + return updownDir; + } + + /** + * The left right direction for the detected face. + * + * @see #startFaceDetection() + */ + public int getLeftRightDirection() { + return leftrightDir; + } + + /** + * The roll direction for the detected face. + * + * @see #startFaceDetection() + */ + public int getRollDirection() { + return rollDir; + } + + /** + * The degree of left eye blink for the detected face. + * + * @see #startFaceDetection() + */ + public int getLeftEyeBlinkDegree() { + return leyeBlink; + } + + /** + * The degree of right eye blink for the detected face. + * + * @see #startFaceDetection() + */ + public int getRightEyeBlinkDegree() { + return reyeBlink; + } + + /** + * The gaze degree of left-right direction for the detected face. + * + * @see #startFaceDetection() + */ + public int getLeftRightGazeDegree() { + return leftrightGaze; + } + + /** + * The gaze degree of up-down direction for the detected face. + * + * @see #startFaceDetection() + */ + public int getTopBottomGazeDegree() { + return topbottomGaze; + } + + private static final String BUNDLE_KEY_SMILE_SCORE = "smileScore"; + private static final String BUNDLE_KEY_SMILE_VALUE = "smileValue"; + private static final String BUNDLE_KEY_BLINK_DETECTED = "blinkDetected"; + private static final String BUNDLE_KEY_LEFT_EYE_CLOSED_VALUE = "leftEyeClosedValue"; + private static final String BUNDLE_KEY_RIGHT_EYE_CLOSED_VALUE = "rightEyeClosedValue"; + private static final String BUNDLE_KEY_FACE_PITCH_DEGREE = "facePitchDegree"; + private static final String BUNDLE_KEY_FACE_YAW_DEGREE = "faceYawDegree"; + private static final String BUNDLE_KEY_FACE_ROLL_DEGREE = "faceRollDegree"; + private static final String BUNDLE_KEY_GAZE_UP_DOWN_DEGREE = "gazeUpDownDegree"; + private static final String BUNDLE_KEY_GAZE_LEFT_RIGHT_DEGREE = "gazeLeftRightDegree"; + private static final String BUNDLE_KEY_FACE_RECOGNIZED = "faceRecognized"; + + public Bundle getQCFaceInfo() { + Bundle faceInfo = new Bundle(); + faceInfo.putInt(BUNDLE_KEY_SMILE_VALUE, this.smileDegree); + + faceInfo.putInt(BUNDLE_KEY_LEFT_EYE_CLOSED_VALUE, this.leyeBlink); + faceInfo.putInt(BUNDLE_KEY_RIGHT_EYE_CLOSED_VALUE, this.reyeBlink); + + faceInfo.putInt(BUNDLE_KEY_FACE_PITCH_DEGREE, this.updownDir); + faceInfo.putInt(BUNDLE_KEY_FACE_YAW_DEGREE, this.leftrightDir); + faceInfo.putInt(BUNDLE_KEY_FACE_ROLL_DEGREE, this.rollDir); + faceInfo.putInt(BUNDLE_KEY_GAZE_UP_DOWN_DEGREE, this.topbottomGaze); + faceInfo.putInt(BUNDLE_KEY_GAZE_LEFT_RIGHT_DEGREE, this.leftrightGaze); + + faceInfo.putInt(BUNDLE_KEY_BLINK_DETECTED, this.blinkDetected); + faceInfo.putInt(BUNDLE_KEY_SMILE_SCORE, this.smileScore); + faceInfo.putInt(BUNDLE_KEY_FACE_RECOGNIZED, this.faceRecognized); + + return faceInfo; + } + +} From c5fada3839062fe46cf0c2ec43e523257cbad5ef Mon Sep 17 00:00:00 2001 From: Emilian Peev Date: Thu, 15 Aug 2013 18:40:41 +0300 Subject: [PATCH 030/204] Camera: Adds support for longshot configuration - The Camera API is extended with one additional call for longshot mode configuration. Change-Id: If3bcad003facae22ec2bd690480dc3db63f0b28a --- core/java/android/hardware/Camera.java | 11 +++++++++++ core/jni/android_hardware_Camera.cpp | 22 ++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 71b8401aa22bb..37a70559e8958 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -1665,6 +1665,17 @@ public final void sendMetaData() } private native final void native_sendMetaData(); + /** @hide + * Configure longshot mode. Available only in ZSL. + * + * @param enable enable/disable this mode + */ + public final void setLongshot(boolean enable) + { + native_setLongshot(enable); + } + private native final void native_setLongshot(boolean enable); + /** @hide * Handles the Touch Co-ordinate. */ diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index aa4b4aab49149..a16a321bfd3e1 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -455,6 +455,25 @@ void JNICameraContext::setCallbackMode(JNIEnv *env, bool installed, bool manualM } } +static void android_hardware_Camera_setLongshot(JNIEnv *env, jobject thiz, jboolean enable) +{ + ALOGV("setLongshot"); + JNICameraContext* context; + status_t rc; + sp camera = get_native_camera(env, thiz, &context); + if (camera == 0) return; + + if ( enable ) { + rc = camera->sendCommand(CAMERA_CMD_LONGSHOT_ON, 0, 0); + } else { + rc = camera->sendCommand(CAMERA_CMD_LONGSHOT_OFF, 0, 0); + } + + if (rc != NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException", "enabling longshot mode failed"); + } +} + static void android_hardware_Camera_sendHistogramData(JNIEnv *env, jobject thiz) { ALOGV("sendHistogramData" ); @@ -1052,6 +1071,9 @@ static JNINativeMethod camMethods[] = { { "native_sendHistogramData", "()V", (void *)android_hardware_Camera_sendHistogramData }, + { "native_setLongshot", + "(Z)V", + (void *)android_hardware_Camera_setLongshot }, { "native_setParameters", "(Ljava/lang/String;)V", (void *)android_hardware_Camera_setParameters }, From 235f202a365a2efc15b06fad47351365678757e1 Mon Sep 17 00:00:00 2001 From: Danny Baumann Date: Thu, 17 Oct 2013 15:53:08 +0200 Subject: [PATCH 031/204] Cleanup and improve ringer tile code. Handle absence of vibrator properly by excluding the respective modes from the selection in that case. Change-Id: I63d1fc06cbbcadadff51866b929dde453f4eb4bd --- .../quicksettings/RingerModeTile.java | 172 +++++++----------- 1 file changed, 70 insertions(+), 102 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/quicksettings/RingerModeTile.java b/packages/SystemUI/src/com/android/systemui/quicksettings/RingerModeTile.java index d3d2b5ece5a79..549268aeefe95 100644 --- a/packages/SystemUI/src/com/android/systemui/quicksettings/RingerModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/quicksettings/RingerModeTile.java @@ -9,39 +9,35 @@ import android.os.Vibrator; import android.provider.Settings; import android.text.TextUtils; -import android.view.LayoutInflater; import android.view.View; -import android.view.View.OnLongClickListener; import com.android.systemui.R; import com.android.systemui.statusbar.phone.QuickSettingsController; -import com.android.systemui.statusbar.phone.QuickSettingsContainerView; -public class RingerModeTile extends QuickSettingsTile { +import java.util.ArrayList; +public class RingerModeTile extends QuickSettingsTile { private static final String SEPARATOR = "OV=I=XseparatorX=I=VO"; - // Define the available ringer modes - private final Ringer mSilentRinger = new Ringer(AudioManager.RINGER_MODE_SILENT, false); - private final Ringer mVibrateRinger = new Ringer(AudioManager.RINGER_MODE_VIBRATE, true); - private final Ringer mSoundRinger = new Ringer(AudioManager.RINGER_MODE_NORMAL, false); - private final Ringer mSoundVibrateRinger = new Ringer(AudioManager.RINGER_MODE_NORMAL, true); - private final Ringer[] mRingers = new Ringer[] { - mSilentRinger, mVibrateRinger, mSoundRinger, mSoundVibrateRinger + private static final Ringer[] RINGERS = new Ringer[] { + new Ringer(AudioManager.RINGER_MODE_SILENT, false, R.drawable.ic_qs_ring_off), + new Ringer(AudioManager.RINGER_MODE_VIBRATE, true, R.drawable.ic_qs_vibrate_on), + new Ringer(AudioManager.RINGER_MODE_NORMAL, false, R.drawable.ic_qs_ring_on), + new Ringer(AudioManager.RINGER_MODE_NORMAL, true, R.drawable.ic_qs_ring_vibrate_on) }; - private int mRingersIndex; - private int[] mRingerValues = new int[] { - 0, 1, 2, 3 - }; - private int mRingerValuesIndex; + private ArrayList mRingers; + private int mRingerIndex; private AudioManager mAudioManager; + private Vibrator mVibrator; public RingerModeTile(Context context, QuickSettingsController qsc) { super(context, qsc); + mRingers = new ArrayList(); mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); // Tile actions mOnClick = new View.OnClickListener() { @@ -52,7 +48,7 @@ public void onClick(View v) { } }; - mOnLongClick = new OnLongClickListener() { + mOnLongClick = new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { startSettingsActivity(android.provider.Settings.ACTION_SOUND_SETTINGS); @@ -60,10 +56,10 @@ public boolean onLongClick(View v) { } }; qsc.registerAction(AudioManager.RINGER_MODE_CHANGED_ACTION, this); - qsc.registerObservedContent(Settings.System.getUriFor(Settings.System.EXPANDED_RING_MODE) - , this); - qsc.registerObservedContent(Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING) - , this); + qsc.registerObservedContent( + Settings.System.getUriFor(Settings.System.EXPANDED_RING_MODE), this); + qsc.registerObservedContent( + Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING), this); } @Override @@ -73,14 +69,14 @@ public void onReceive(Context context, Intent intent) { @Override public void onChangeUri(ContentResolver resolver, Uri uri) { - updateSettings(mContext.getContentResolver()); + updateSettings(); updateResources(); } @Override void onPostCreate() { // Load the available ringer modes - updateSettings(mContext.getContentResolver()); + updateSettings(); // Make sure we show the initial state correctly updateTile(); @@ -94,125 +90,97 @@ public void updateResources() { super.updateResources(); } - private synchronized void updateTile() { + private void updateTile() { // The title does not change mLabel = mContext.getString(R.string.quick_settings_ringer_normal); // The icon will change depending on index findCurrentState(); - switch (mRingersIndex) { - case 0: - mDrawable = R.drawable.ic_qs_ring_off; - break; - case 1: - mDrawable = R.drawable.ic_qs_vibrate_on; - break; - case 2: - mDrawable = R.drawable.ic_qs_ring_on; - break; - case 3: - mDrawable = R.drawable.ic_qs_ring_vibrate_on; - break; - } - - for (int i = 0; i < mRingerValues.length; i++) { - if (mRingersIndex == mRingerValues[i]) { - mRingerValuesIndex = i; - break; - } - } + mDrawable = mRingers.get(mRingerIndex).mDrawable; } protected void toggleState() { - mRingerValuesIndex++; - if (mRingerValuesIndex > mRingerValues.length - 1) { - mRingerValuesIndex = 0; + mRingerIndex++; + if (mRingerIndex >= mRingers.size()) { + mRingerIndex = 0; } - mRingersIndex = mRingerValues[mRingerValuesIndex]; - if (mRingersIndex > mRingers.length - 1) { - mRingersIndex = 0; + Ringer r = mRingers.get(mRingerIndex); + + // If we are setting a vibrating state, vibrate to indicate it + if (r.mVibrateWhenRinging) { + mVibrator.vibrate(250); } - Ringer ringer = mRingers[mRingersIndex]; - ringer.execute(mContext); + // Set the desired state + ContentResolver resolver = mContext.getContentResolver(); + Settings.System.putIntForUser(resolver, Settings.System.VIBRATE_WHEN_RINGING, + r.mVibrateWhenRinging ? 1 : 0, UserHandle.USER_CURRENT); + mAudioManager.setRingerMode(r.mRingerMode); } public String[] parseStoredValue(CharSequence val) { if (TextUtils.isEmpty(val)) { - return null; - } else { - return val.toString().split(SEPARATOR); + return null; } + return val.toString().split(SEPARATOR); } - private void updateSettings(ContentResolver resolver) { - String[] modes = parseStoredValue(Settings.System.getStringForUser( - resolver, Settings.System.EXPANDED_RING_MODE, UserHandle.USER_CURRENT)); + private void updateSettings() { + String setting = Settings.System.getStringForUser(mContext.getContentResolver(), + Settings.System.EXPANDED_RING_MODE, UserHandle.USER_CURRENT); + String[] modes = parseStoredValue(setting); + Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); + boolean hasVibrator = vibrator.hasVibrator(); + + mRingers.clear(); + if (modes == null || modes.length == 0) { - mRingerValues = new int[] { - 0, 1, 2, 3 - }; + for (Ringer r : RINGERS) { + if (hasVibrator || !r.mVibrateWhenRinging) { + mRingers.add(r); + } + } } else { - mRingerValues = new int[modes.length]; for (int i = 0; i < modes.length; i++) { - mRingerValues[i] = Integer.valueOf(modes[i]); + int index = Integer.valueOf(modes[i]); + Ringer r = index < RINGERS.length ? RINGERS[index] : null; + + if (r != null && (hasVibrator || !r.mVibrateWhenRinging)) { + mRingers.add(r); + } } } + if (mRingers.isEmpty()) { + mRingers.add(RINGERS[0]); + } } private void findCurrentState() { - ContentResolver resolver = mContext.getContentResolver(); - boolean vibrateWhenRinging = Settings.System.getIntForUser(resolver, + boolean vibrateWhenRinging = Settings.System.getIntForUser(mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0, UserHandle.USER_CURRENT) == 1; int ringerMode = mAudioManager.getRingerMode(); - Ringer ringer = new Ringer(ringerMode, vibrateWhenRinging); - for (int i = 0; i < mRingers.length; i++) { - if (mRingers[i].equals(ringer)) { - mRingersIndex = i; + mRingerIndex = 0; + + for (int i = 0; i < mRingers.size(); i++) { + Ringer r = mRingers.get(i); + if (ringerMode == r.mRingerMode && vibrateWhenRinging == r.mVibrateWhenRinging) { + mRingerIndex = i; break; } } } - private class Ringer { + private static class Ringer { final boolean mVibrateWhenRinging; final int mRingerMode; + final int mDrawable; - Ringer( int ringerMode, boolean vibrateWhenRinging) { + Ringer(int ringerMode, boolean vibrateWhenRinging, int drawable) { mVibrateWhenRinging = vibrateWhenRinging; mRingerMode = ringerMode; - } - - void execute(Context context) { - // If we are setting a vibrating state, vibrate to indicate it - if (mVibrateWhenRinging) { - Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); - vibrator.vibrate(250); - } - - // Set the desired state - ContentResolver resolver = context.getContentResolver(); - Settings.System.putIntForUser(resolver, Settings.System.VIBRATE_WHEN_RINGING, - mVibrateWhenRinging ? 1 : 0, UserHandle.USER_CURRENT); - mAudioManager.setRingerMode(mRingerMode); - } - - @Override - public boolean equals(Object o) { - if (o == null) { - return false; - } - if (o.getClass() != getClass()) { - return false; - } - Ringer r = (Ringer) o; - if ((mRingerMode == AudioManager.RINGER_MODE_SILENT || mRingerMode == AudioManager.RINGER_MODE_VIBRATE) - && (r.mRingerMode == mRingerMode)) - return true; - return r.mVibrateWhenRinging == mVibrateWhenRinging - && r.mRingerMode == mRingerMode; + mDrawable = drawable; } } } From 227ec12643a87480563d214bdf1f88743053dcdb Mon Sep 17 00:00:00 2001 From: Thomas Wendt Date: Thu, 17 Oct 2013 19:00:05 +0200 Subject: [PATCH 032/204] Fix compilation for non QCOM hardware after 'Enhance face detection' commit Change-Id: I337a7a2e8b124aac76f52abcc0edd8af9b0b0e29 --- core/jni/android_hardware_Camera.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index a16a321bfd3e1..6ca217f13752b 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -53,6 +53,7 @@ struct fields_t { jfieldID face_leftEye; jfieldID face_rightEye; jfieldID face_mouth; +#ifdef QCOM_HARDWARE jfieldID face_sm_degree; jfieldID face_sm_score; jfieldID face_blink_detected; @@ -64,6 +65,7 @@ struct fields_t { jfieldID face_reye_blink; jfieldID face_left_right_gaze; jfieldID face_top_bottom_gaze; +#endif jfieldID face_recognised; jfieldID point_x; jfieldID point_y; @@ -401,6 +403,7 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m env->SetIntField(face, fields.face_id, metadata->faces[i].id); +#ifdef QCOM_HARDWARE if (mIsQcFace) { env->SetIntField(face, fields.face_sm_degree, metadata->faces[i].smile_degree); env->SetIntField(face, fields.face_sm_score, metadata->faces[i].smile_score); @@ -415,6 +418,7 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m env->SetIntField(face, fields.face_left_right_gaze, metadata->faces[i].left_right_gaze); env->SetIntField(face, fields.face_top_bottom_gaze, metadata->faces[i].top_bottom_gaze); } +#endif env->DeleteLocalRef(face); env->DeleteLocalRef(rect); @@ -1168,9 +1172,11 @@ int register_android_hardware_Camera(JNIEnv *env) { "android/hardware/Camera$Face", "leftEye", "Landroid/graphics/Point;", &fields.face_leftEye }, { "android/hardware/Camera$Face", "rightEye", "Landroid/graphics/Point;", &fields.face_rightEye }, { "android/hardware/Camera$Face", "mouth", "Landroid/graphics/Point;", &fields.face_mouth }, +#ifdef QCOM_HARDWARE { "android/hardware/Camera$Face", "smileDegree", "I", &fields.face_sm_degree }, { "android/hardware/Camera$Face", "smileScore", "I", &fields.face_sm_score }, { "android/hardware/Camera$Face", "blinkDetected", "I", &fields.face_blink_detected }, +#endif { "android/hardware/Camera$Face", "faceRecognised", "I", &fields.face_recognised }, }; @@ -1178,6 +1184,7 @@ int register_android_hardware_Camera(JNIEnv *env) { "org/codeaurora/camera/QCFace", "rect", "Landroid/graphics/Rect;", &fields.face_rect }, { "org/codeaurora/camera/QCFace", "score", "I", &fields.face_score }, { "org/codeaurora/camera/QCFace", "id", "I", &fields.face_id }, +#ifdef QCOM_HARDWARE { "org/codeaurora/camera/QCFace", "leftEye", "Landroid/graphics/Point;", &fields.face_leftEye }, { "org/codeaurora/camera/QCFace", "rightEye", "Landroid/graphics/Point;", &fields.face_rightEye }, { "org/codeaurora/camera/QCFace", "mouth", "Landroid/graphics/Point;", &fields.face_mouth }, @@ -1193,6 +1200,7 @@ int register_android_hardware_Camera(JNIEnv *env) { "org/codeaurora/camera/QCFace", "reyeBlink", "I", &fields.face_reye_blink }, { "org/codeaurora/camera/QCFace", "leftrightGaze", "I", &fields.face_left_right_gaze }, { "org/codeaurora/camera/QCFace", "topbottomGaze", "I", &fields.face_top_bottom_gaze }, +#endif }; if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0) From 20623512c14a90978db88d307858d731fcd93f55 Mon Sep 17 00:00:00 2001 From: Kim Zhang Date: Thu, 29 Aug 2013 17:21:51 +0800 Subject: [PATCH 033/204] MediaRecorder: add pause interface --add pause in java level --add pause in jni level Change-Id: I7f2d5d5ebb97716458b55a5780fd6cc3d09e9f11 --- media/java/android/media/MediaRecorder.java | 4 ++++ media/jni/android_media_MediaRecorder.cpp | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 75af5249c2a3f..04ca39a78a894 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -712,6 +712,10 @@ public void prepare() throws IllegalStateException, IOException */ public native void start() throws IllegalStateException; +/** @hide +*/ + public native void pause() throws IllegalStateException; + /** * Stops recording. Call this after start(). Once recording is stopped, * you will have to configure it again as if it has just been constructed. diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp index 98885911b86f4..eff4977d8e7fb 100644 --- a/media/jni/android_media_MediaRecorder.cpp +++ b/media/jni/android_media_MediaRecorder.cpp @@ -352,6 +352,14 @@ android_media_MediaRecorder_start(JNIEnv *env, jobject thiz) process_media_recorder_call(env, mr->start(), "java/lang/RuntimeException", "start failed."); } +static void +android_media_MediaRecorder_pause(JNIEnv *env, jobject thiz) +{ + ALOGV("pause"); + sp mr = getMediaRecorder(env, thiz); + process_media_recorder_call(env, mr->pause(), "java/lang/RuntimeException", "pause failed."); +} + static void android_media_MediaRecorder_stop(JNIEnv *env, jobject thiz) { @@ -472,6 +480,7 @@ static JNINativeMethod gMethods[] = { {"_prepare", "()V", (void *)android_media_MediaRecorder_prepare}, {"getMaxAmplitude", "()I", (void *)android_media_MediaRecorder_native_getMaxAmplitude}, {"start", "()V", (void *)android_media_MediaRecorder_start}, + {"pause", "()V", (void *)android_media_MediaRecorder_pause}, {"stop", "()V", (void *)android_media_MediaRecorder_stop}, {"native_reset", "()V", (void *)android_media_MediaRecorder_native_reset}, {"release", "()V", (void *)android_media_MediaRecorder_release}, From 980bf5b4f18a0d48df11e181fd82eb0c27724921 Mon Sep 17 00:00:00 2001 From: Alex Yakavenka Date: Mon, 18 Jun 2012 13:59:36 -0700 Subject: [PATCH 034/204] Telephony: Add new apn.sim.operator_numeric property Use new property to filter apns. We need this new property because icc.operator_numeric property is also used in cdma and ApnSetting UI might display wrong set of apns if the peroperty value used was set by RuimRecords CRs-Fixed: 362846 Change-Id: I3831a703a2fdc69df8552af57e0bb981d0c7e46f --- .../com/android/internal/telephony/TelephonyProperties.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index 3427bf63ae295..6c725d67b92e7 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -108,6 +108,12 @@ public interface TelephonyProperties */ static String PROPERTY_ICC_OPERATOR_NUMERIC = "gsm.sim.operator.numeric"; + /** The MCC+MNC (mobile country code+mobile network code) of the + * provider of the SIM to be used for APNs lookup. 5 or 6 decimal digits. + * Availability: SIM state must be "READY" + */ + static String PROPERTY_APN_SIM_OPERATOR_NUMERIC = "gsm.apn.sim.operator.numeric"; + /** PROPERTY_ICC_OPERATOR_ALPHA is also known as the SPN, or Service Provider Name. * Availability: SIM state must be "READY" */ From 7eaefaf413b1bb12e6ede54eeb0eae3e958bde4e Mon Sep 17 00:00:00 2001 From: Rakesh Pallerla Date: Wed, 6 Feb 2013 11:44:23 +0530 Subject: [PATCH 035/204] Telephony: Add functionality to handle ICC IO error At present in Android all ICC Card states other than ICC PRESENT are treated as ICC ABSENT.Adding functionality to handle ICC IO error card state. CRs-Fixed: 184479 Change-Id: Id6a8cf8c7bb2ed441bf8db15b84c4e426537fdb1 --- core/res/res/values/strings.xml | 5 +++++ .../systemui/statusbar/phone/PhoneStatusBarPolicy.java | 3 +++ telephony/java/android/telephony/TelephonyManager.java | 8 ++++++++ .../com/android/internal/telephony/IccCardConstants.java | 7 +++++-- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 04e8fcd343b30..f63fe19a32571 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -2205,6 +2205,11 @@ Emergency calls only + + Invalid Card. + + SIM card is Invalid. + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index 9b8bd224e7fa4..8561192ac39b0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -210,6 +210,9 @@ private final void updateSimState(Intent intent) { if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { mSimState = IccCardConstants.State.ABSENT; } + else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) { + mSimState = IccCardConstants.State.CARD_IO_ERROR; + } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) { mSimState = IccCardConstants.State.READY; } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 19e77b6d02f4f..b351a1510c83c 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -801,6 +801,10 @@ public static String getNetworkTypeName(int type) { public static final int SIM_STATE_NETWORK_LOCKED = 4; /** SIM card state: Ready */ public static final int SIM_STATE_READY = 5; + /** SIM card state: SIM Card Error, Sim Card is present but faulty + *@hide + */ + public static final int SIM_STATE_CARD_IO_ERROR = 6; /** * @return true if a ICC card is present @@ -827,6 +831,7 @@ public boolean hasIccCard() { * @see #SIM_STATE_PUK_REQUIRED * @see #SIM_STATE_NETWORK_LOCKED * @see #SIM_STATE_READY + * @see #SIM_STATE_CARD_IO_ERROR */ public int getSimState() { String prop = SystemProperties.get(TelephonyProperties.PROPERTY_SIM_STATE); @@ -845,6 +850,9 @@ else if ("NETWORK_LOCKED".equals(prop)) { else if ("READY".equals(prop)) { return SIM_STATE_READY; } + else if ("CARD_IO_ERROR".equals(prop)) { + return SIM_STATE_CARD_IO_ERROR; + } else { return SIM_STATE_UNKNOWN; } diff --git a/telephony/java/com/android/internal/telephony/IccCardConstants.java b/telephony/java/com/android/internal/telephony/IccCardConstants.java index 236bb2fb5a571..80297132ab7be 100644 --- a/telephony/java/com/android/internal/telephony/IccCardConstants.java +++ b/telephony/java/com/android/internal/telephony/IccCardConstants.java @@ -28,6 +28,8 @@ public class IccCardConstants { public static final String INTENT_VALUE_ICC_NOT_READY = "NOT_READY"; /* ABSENT means ICC is missing */ public static final String INTENT_VALUE_ICC_ABSENT = "ABSENT"; + /* CARD_IO_ERROR means for three consecutive times there was SIM IO error */ + static public final String INTENT_VALUE_ICC_CARD_IO_ERROR = "CARD_IO_ERROR"; /* LOCKED means ICC is locked by pin or by network */ public static final String INTENT_VALUE_ICC_LOCKED = "LOCKED"; /* READY means ICC is ready to access */ @@ -63,7 +65,8 @@ public enum State { NETWORK_LOCKED, READY, NOT_READY, - PERM_DISABLED; + PERM_DISABLED, + CARD_IO_ERROR; public boolean isPinLocked() { return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED)); @@ -72,7 +75,7 @@ public boolean isPinLocked() { public boolean iccCardExist() { return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED) || (this == NETWORK_LOCKED) || (this == READY) - || (this == PERM_DISABLED)); + || (this == PERM_DISABLED) || (this == CARD_IO_ERROR)); } } } From 9a51a3ded44815316258d4c91ee143fe27efa2b5 Mon Sep 17 00:00:00 2001 From: Sandeep Gutta Date: Thu, 3 Jan 2013 19:12:17 +0530 Subject: [PATCH 036/204] Telephony: Managed Roaming feature re-design. Change-Id: I79c7ea2e647617e58526b5b550406214455a58aa --- .../android/internal/telephony/TelephonyIntents.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java index 40a3c8fceb357..084798971e100 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java +++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java @@ -298,4 +298,16 @@ public class TelephonyIntents { public static final String EXTRA_PLMN = "plmn"; public static final String EXTRA_SHOW_SPN = "showSpn"; public static final String EXTRA_SPN = "spn"; + + /** + * Managed Roaming Intent. Used by Phone App to show popup to the end user that location update + * request rejected with status as "Persistent location update reject", so user can try to do + * location update on other Network:

+ * + *

This is a protected intent that can only be sent + * by the system. + * @hide + */ + public static final String ACTION_MANAGED_ROAMING_IND + = "qualcomm.intent.action.ACTION_MANAGED_ROAMING_IND"; } From cf1e40271c4e3b8085c5dae776f7be5aeb74918c Mon Sep 17 00:00:00 2001 From: Rakesh Pallerla Date: Mon, 21 Jan 2013 13:23:51 +0530 Subject: [PATCH 037/204] Telephony: Few PIN/PUK fixes Following changes have been made as part of this: -> Changes done to display retry counter on wrong entry of PIN1,and message to indicate Code accepted/PIN1 blocked during PIN1 verification as per certain carrier requirements. ->The current APIs that are used to verify the PIN and PUK only convey whether the operation succeeded or failed. As a result on ANY failure clients ask the user to re-enter the PIN. Add 2 new APIs that report the actual error code in case of failure. ->Display the complete text including attempts remaining to unlock PIN on SimUnlockScreen if user entered incorrect PIN. On some devices the display text is ellipsized when trying to display on a single line. CRs-Fixed: 184479, 260481, 181402, 181380, 181401, 326286, 441001, 479414, 479417 Change-Id: I73718c9e6a8aa7244097e0dd4593a6226ff0ac08 --- .../res/res/layout/transient_notification.xml | 1 + core/res/res/values/strings.xml | 27 +++++++++++-- core/res/res/values/symbols.xml | 8 ++++ .../statusbar/policy/NetworkController.java | 3 ++ .../policy/impl/keyguard/CarrierText.java | 11 ++++- .../impl/keyguard/KeyguardSimPinView.java | 40 ++++++++++++++----- .../impl/keyguard/KeyguardSimPukView.java | 39 ++++++++++++++---- .../impl/keyguard/KeyguardUpdateMonitor.java | 2 + .../internal/telephony/ITelephony.aidl | 23 +++++++++++ .../internal/telephony/PhoneConstants.java | 8 ++++ 10 files changed, 139 insertions(+), 23 deletions(-) diff --git a/core/res/res/layout/transient_notification.xml b/core/res/res/layout/transient_notification.xml index 5523807d65480..cd921ef611584 100644 --- a/core/res/res/layout/transient_notification.xml +++ b/core/res/res/layout/transient_notification.xml @@ -19,6 +19,7 @@ --> Your SIM card is PUK-locked. Type the PUK code to unlock it. Type PUK2 to unblock SIM card. + + Unsuccessful. Enable SIM/RUIM Lock. IMEI @@ -2126,6 +2128,25 @@ to unlock the keyguard. Displayed in one line in a large font. --> Incorrect PIN code. + + Incorrect PUK code! + + + PIN operation failed! + + + PUK operation failed! + + + + Code Accepted! + + + \nAttempts Remaining : + To unlock, press Menu then 0. @@ -2220,10 +2241,10 @@ PUK locked (Pin Unlock Kode) --> SIM card is PUK-locked. - See the User Guide or contact Customer Care. + PIN1 Blocked. Enter PUK1.\nor\nPlease see the User Guide or contact Customer Care. - - SIM card is locked. + + SIM/RUIM card is locked. No application found to handle this action Revoke + + + USSD request is modified to DIAL request. + USSD request is modified to SS request. + USSD request is modified to new USSD request. + SS request is modified to DIAL request. + SS request is modified to USSD request. + SS request is modified to new SS request. + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index f1f053b60cd6a..45c0ba243b071 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -886,6 +886,12 @@ + + + + + + diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index c73b76391a865..f0f2c25f16f6f 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -56,6 +56,15 @@ class C */ int ILLEGAL_SIM_OR_ME = 15; /* network selection failure due to wrong SIM/ME and no retries needed */ + int DIAL_MODIFIED_TO_USSD = 17; /* DIAL request modified to USSD */ + int DIAL_MODIFIED_TO_SS = 18; /* DIAL request modified to SS */ + int DIAL_MODIFIED_TO_DIAL = 19; /* DIAL request modified to DIAL with different data */ + int USSD_MODIFIED_TO_DIAL = 20; /* USSD request modified to DIAL */ + int USSD_MODIFIED_TO_SS = 21; /* USSD request modified to SS */ + int USSD_MODIFIED_TO_USSD = 22; /* USSD request modified to different USSD request */ + int SS_MODIFIED_TO_DIAL = 23; /* SS request modified to DIAL */ + int SS_MODIFIED_TO_USSD = 24; /* SS request modified to USSD */ + int SS_MODIFIED_TO_SS = 25; /* SS request modified to different SS request */ /* NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE */ int NETWORK_MODE_WCDMA_PREF = 0; /* GSM/WCDMA (WCDMA preferred) */ @@ -312,6 +321,8 @@ class C */ int RIL_UNSOL_CELL_INFO_LIST = 1036; int RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED = 1037; int RIL_UNSOL_TETHERED_MODE_STATE_CHANGED = 1038; + int RIL_UNSOL_ON_SS = 1039; + int RIL_UNSOL_STK_CC_ALPHA_NOTIFY = 1040; int RIL_UNSOL_STK_SEND_SMS_RESULT = 11002; /* Samsung STK */ } From e74d0178b4e1f0c585ef50617d7b9d292c59d40a Mon Sep 17 00:00:00 2001 From: Srikanth Chintala Date: Sun, 21 Oct 2012 02:20:06 -0700 Subject: [PATCH 044/204] Telephony: Initialize GsmCellLocation class members properly Default values for class members mLac, mCid, mPsc would be 0. Initialize these variables with -1 as 0 is considered as valid value. CRs-Fixed: 406479 Change-Id: I08dc4031bb16293e80e5b7f51afcb8dc11747d3b --- .../java/android/telephony/gsm/GsmCellLocation.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/telephony/java/android/telephony/gsm/GsmCellLocation.java b/telephony/java/android/telephony/gsm/GsmCellLocation.java index 313bc82a07ffa..28360da0e73ce 100644 --- a/telephony/java/android/telephony/gsm/GsmCellLocation.java +++ b/telephony/java/android/telephony/gsm/GsmCellLocation.java @@ -23,17 +23,14 @@ * Represents the cell location on a GSM phone. */ public class GsmCellLocation extends CellLocation { - private int mLac; - private int mCid; - private int mPsc; + private int mLac = -1; + private int mCid = -1; + private int mPsc = -1; /** - * Empty constructor. Initializes the LAC and CID to -1. + * Empty constructor. */ public GsmCellLocation() { - mLac = -1; - mCid = -1; - mPsc = -1; } /** From f0c330feaf472b7da98491ddba2370e23ba22aba Mon Sep 17 00:00:00 2001 From: Rakesh Pallerla Date: Tue, 18 Jun 2013 17:58:02 +0530 Subject: [PATCH 045/204] Telephony(MSIM): Add support for MultiSim Make changes to add support for MultiSim. -Add TelephonyManager and TelePhonyRegistry for MultiSim -Add ITelephony and IPhoneSubinfo aidl files for MultiSim -Extend ShutdownThread to close all radio's for MultiSim -Add Constants and Utils used for MultiSim Change-Id: I6ee5d2a22e44fe7d0d68a41af0481ddbbbe21c3f --- Android.mk | 5 + core/java/android/app/ContextImpl.java | 10 + core/java/android/content/Context.java | 16 +- .../android/net/MobileDataStateTracker.java | 86 +- core/java/android/provider/Settings.java | 41 + .../providers/settings/DatabaseHelper.java | 15 +- .../android/server/MSimTelephonyRegistry.java | 864 +++++++++++++ .../java/com/android/server/SystemServer.java | 16 + .../android/server/power/ShutdownThread.java | 44 +- .../telephony/MSimTelephonyManager.java | 1134 +++++++++++++++++ .../android/telephony/PhoneNumberUtils.java | 18 +- .../android/telephony/PhoneStateListener.java | 19 + .../android/telephony/TelephonyManager.java | 56 +- .../telephony/ITelephonyRegistryMSim.aidl | 48 + .../internal/telephony/MSimConstants.java | 60 + .../internal/telephony/RILConstants.java | 10 +- .../telephony/TelephonyProperties.java | 14 + .../telephony/msim/IPhoneSubInfoMSim.aidl | 82 ++ .../telephony/msim/ITelephonyMSim.aidl | 347 +++++ 19 files changed, 2849 insertions(+), 36 deletions(-) create mode 100644 services/java/com/android/server/MSimTelephonyRegistry.java create mode 100644 telephony/java/android/telephony/MSimTelephonyManager.java create mode 100644 telephony/java/com/android/internal/telephony/ITelephonyRegistryMSim.aidl create mode 100644 telephony/java/com/android/internal/telephony/MSimConstants.java create mode 100644 telephony/java/com/android/internal/telephony/msim/IPhoneSubInfoMSim.aidl create mode 100644 telephony/java/com/android/internal/telephony/msim/ITelephonyMSim.aidl diff --git a/Android.mk b/Android.mk index 5094048850dcb..5eedd427278cb 100644 --- a/Android.mk +++ b/Android.mk @@ -237,9 +237,12 @@ LOCAL_SRC_FILES += \ media/java/android/media/IRingtonePlayer.aidl \ telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \ telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \ + telephony/java/com/android/internal/telephony/msim/IPhoneSubInfoMSim.aidl \ telephony/java/com/android/internal/telephony/ITelephony.aidl \ + telephony/java/com/android/internal/telephony/msim/ITelephonyMSim.aidl \ telephony/java/com/android/internal/telephony/ISms.aidl \ telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \ + telephony/java/com/android/internal/telephony/ITelephonyRegistryMSim.aidl \ telephony/java/com/android/internal/telephony/IWapPushManager.aidl \ wifi/java/android/net/wifi/IWifiManager.aidl \ wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \ @@ -351,7 +354,9 @@ aidl_files := \ frameworks/base/location/java/com/android/internal/location/ProviderRequest.aidl \ frameworks/base/telephony/java/android/telephony/ServiceState.aidl \ frameworks/base/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \ + frameworks/base/telephony/java/com/android/internal/telephony/msim/IPhoneSubInfoMSim.aidl \ frameworks/base/telephony/java/com/android/internal/telephony/ITelephony.aidl \ + frameworks/base/telephony/java/com/android/internal/telephony/msim/ITelephonyMSim.aidl \ gen := $(TARGET_OUT_COMMON_INTERMEDIATES)/framework.aidl $(gen): PRIVATE_SRC_FILES := $(aidl_files) diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 3a63a2a82bcb4..417785501c16e 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1,6 +1,8 @@ /* * Copyright (C) 2006 The Android Open Source Project * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc. + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -98,6 +100,7 @@ import android.os.SystemVibrator; import android.os.UserManager; import android.os.storage.StorageManager; +import android.telephony.MSimTelephonyManager; import android.telephony.TelephonyManager; import android.content.ClipboardManager; import android.util.AndroidRuntimeException; @@ -489,6 +492,13 @@ public Object createService(ContextImpl ctx) { return new TelephonyManager(ctx.getOuterContext()); }}); + if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) { + registerService(MSIM_TELEPHONY_SERVICE, new ServiceFetcher() { + public Object createService(ContextImpl ctx) { + return new MSimTelephonyManager(ctx.getOuterContext()); + }}); + } + registerService(UI_MODE_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { return new UiModeManager(); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 78846c2395cea..0cd4c75e90b42 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1,5 +1,8 @@ /* * Copyright (C) 2006 The Android Open Source Project + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Not a Contribution. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -1650,7 +1653,7 @@ public abstract Intent registerReceiverAsUser(BroadcastReceiver receiver, * @hide like {@link #stopService(Intent)} but for a specific user. */ public abstract boolean stopServiceAsUser(Intent service, UserHandle user); - + /** * Connect to an application service, creating it if needed. This defines * a dependency between your application and the service. The given @@ -2135,6 +2138,17 @@ public abstract boolean startInstrumentation(ComponentName className, */ public static final String TELEPHONY_SERVICE = "phone"; + /** + * Use with {@link #getSystemService} to retrieve a + * {android.telephony.MSimTelephonyManager} for handling the management + * of the telephony features of the multi sim device. + * + * @see #getSystemService + * @see android.telephony.MSimTelephonyManager + * @hide + */ + public static final String MSIM_TELEPHONY_SERVICE = "phone_msim"; + /** * Use with {@link #getSystemService} to retrieve a * {@link android.text.ClipboardManager} for accessing and modifying diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java index 75c402cb5ba94..c93e6f0f8ac8c 100644 --- a/core/java/android/net/MobileDataStateTracker.java +++ b/core/java/android/net/MobileDataStateTracker.java @@ -1,5 +1,8 @@ /* * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Not a Contribution. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,12 +31,14 @@ import android.os.Messenger; import android.os.RemoteException; import android.os.ServiceManager; +import android.telephony.MSimTelephonyManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Slog; import com.android.internal.telephony.DctConstants; import com.android.internal.telephony.ITelephony; +import com.android.internal.telephony.msim.ITelephonyMSim; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.util.AsyncChannel; @@ -57,6 +62,7 @@ public class MobileDataStateTracker implements NetworkStateTracker { private PhoneConstants.DataState mMobileDataState; private ITelephony mPhoneService; + private ITelephonyMSim mMSimPhoneService; private String mApnType; private NetworkInfo mNetworkInfo; @@ -315,6 +321,13 @@ public void onReceive(Context context, Intent intent) { } private void getPhoneService(boolean forceRefresh) { + if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) { + if (mMSimPhoneService == null || forceRefresh) { + mMSimPhoneService = ITelephonyMSim.Stub.asInterface( + ServiceManager.getService("phone_msim")); + } + return; + } if ((mPhoneService == null) || forceRefresh) { mPhoneService = ITelephony.Stub.asInterface(ServiceManager.getService("phone")); } @@ -499,15 +512,33 @@ public boolean setRadio(boolean turnOn) { * RemoteException and need to re-reference the service. */ for (int retry = 0; retry < 2; retry++) { - if (mPhoneService == null) { - loge("Ignoring mobile radio request because could not acquire PhoneService"); - break; - } + if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) { + if (mMSimPhoneService == null) { + loge("Ignoring mobile radio request because " + + "could not acquire MSim Phone Service"); + break; + } - try { - return mPhoneService.setRadio(turnOn); - } catch (RemoteException e) { - if (retry == 0) getPhoneService(true); + try { + boolean result = true; + for (int i = 0; i < MSimTelephonyManager.getDefault().getPhoneCount(); i++) { + result = result && mMSimPhoneService.setRadio(turnOn, i); + } + return result; + } catch (RemoteException e) { + if (retry == 0) getPhoneService(true); + } + } else { + if (mPhoneService == null) { + loge("Ignoring mobile radio request because could not acquire PhoneService"); + break; + } + + try { + return mPhoneService.setRadio(turnOn); + } catch (RemoteException e) { + if (retry == 0) getPhoneService(true); + } } } @@ -638,19 +669,36 @@ private int setEnableApn(String apnType, boolean enable) { * RemoteException and need to re-reference the service. */ for (int retry = 0; retry < 2; retry++) { - if (mPhoneService == null) { - loge("Ignoring feature request because could not acquire PhoneService"); - break; - } + if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) { + if (mMSimPhoneService == null) { + loge("Ignoring feature request because could not acquire MSim Phone Service"); + break; + } - try { - if (enable) { - return mPhoneService.enableApnType(apnType); - } else { - return mPhoneService.disableApnType(apnType); + try { + if (enable) { + return mMSimPhoneService.enableApnType(apnType); + } else { + return mMSimPhoneService.disableApnType(apnType); + } + } catch (RemoteException e) { + if (retry == 0) getPhoneService(true); + } + } else { + if (mPhoneService == null) { + loge("Ignoring feature request because could not acquire PhoneService"); + break; + } + + try { + if (enable) { + return mPhoneService.enableApnType(apnType); + } else { + return mPhoneService.disableApnType(apnType); + } + } catch (RemoteException e) { + if (retry == 0) getPhoneService(true); } - } catch (RemoteException e) { - if (retry == 0) getPhoneService(true); } } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index e9d553b3996b0..dd7fbc4a54a89 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1,5 +1,8 @@ /* * Copyright (C) 2006 The Android Open Source Project + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Not a Contribution. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -6914,6 +6917,44 @@ public static float getFloat(ContentResolver cr, String name) public static boolean putFloat(ContentResolver cr, String name, float value) { return putString(cr, name, Float.toString(value)); } + + + /** + * Subscription to be used for voice call on a multi sim device. The supported values + * are 0 = SUB1, 1 = SUB2 and etc. + * @hide + */ + public static final String MULTI_SIM_VOICE_CALL_SUBSCRIPTION = "multi_sim_voice_call"; + + /** + * Used to provide option to user to select subscription during dial. + * The supported values are 0 = disable or 1 = enable prompt. + * @hide + */ + public static final String MULTI_SIM_VOICE_PROMPT = "multi_sim_voice_prompt"; + + /** + * Subscription to be used for data call on a multi sim device. The supported values + * are 0 = SUB1, 1 = SUB2 and etc. + * @hide + */ + public static final String MULTI_SIM_DATA_CALL_SUBSCRIPTION = "multi_sim_data_call"; + + /** + * Subscription to be used for SMS on a multi sim device. The supported values + * are 0 = SUB1, 1 = SUB2 and etc. + * @hide + */ + public static final String MULTI_SIM_SMS_SUBSCRIPTION = "multi_sim_sms"; + + /** User preferred subscriptions setting. + * This holds the details of the user selected subscription from the card and + * the activation status. Each settings string have the coma separated values + * iccId,appType,appId,activationStatus,3gppIndex,3gpp2Index + * @hide + */ + public static final String[] MULTI_SIM_USER_PREFERRED_SUBS = {"user_preferred_sub1", + "user_preferred_sub2","user_preferred_sub3"}; } /** diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index a0167690eb28c..75f25f4973242 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -1,5 +1,8 @@ /* * Copyright (C) 2007 The Android Open Source Project + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Not a Contribution. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,6 +42,7 @@ import android.provider.Settings; import android.provider.Settings.Global; import android.provider.Settings.Secure; +import android.telephony.MSimTelephonyManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; @@ -2300,9 +2304,18 @@ private void loadGlobalSettings(SQLiteDatabase db) { // Set the preferred network mode to 0 = Global, CDMA default int type; + if (TelephonyManager.getLteOnCdmaModeStatic() == PhoneConstants.LTE_ON_CDMA_TRUE) { + type = Phone.NT_MODE_GLOBAL; + } else { type = SystemProperties.getInt("ro.telephony.default_network", RILConstants.PREFERRED_NETWORK_MODE); - loadSetting(stmt, Settings.Global.PREFERRED_NETWORK_MODE, type); + } + + String val = Integer.toString(type); + if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) { + val = type + "," + type; + } + loadSetting(stmt, Settings.Global.PREFERRED_NETWORK_MODE, val); // --- New global settings start here } finally { diff --git a/services/java/com/android/server/MSimTelephonyRegistry.java b/services/java/com/android/server/MSimTelephonyRegistry.java new file mode 100644 index 0000000000000..ee9ad9b21fe41 --- /dev/null +++ b/services/java/com/android/server/MSimTelephonyRegistry.java @@ -0,0 +1,864 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. + * + * Not a Contribution. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.app.ActivityManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.net.LinkCapabilities; +import android.net.LinkProperties; +import android.os.Binder; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.Message; +import android.os.RemoteException; +import android.os.UserHandle; +import android.telephony.CellInfo; +import android.telephony.CellLocation; +import android.telephony.MSimTelephonyManager; +import android.telephony.PhoneStateListener; +import android.telephony.ServiceState; +import android.telephony.SignalStrength; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.Slog; + +import java.util.ArrayList; +import java.util.List; +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.net.NetworkInterface; + +import com.android.internal.app.IBatteryStats; +import com.android.internal.telephony.ITelephonyRegistryMSim; +import com.android.internal.telephony.IPhoneStateListener; +import com.android.internal.telephony.DefaultPhoneNotifier; +import com.android.internal.telephony.MSimConstants; +import com.android.internal.telephony.Phone; +import com.android.internal.telephony.PhoneConstants; +import com.android.internal.telephony.ServiceStateTracker; +import com.android.internal.telephony.TelephonyIntents; +import com.android.server.am.BatteryStatsService; + +/** + * Since phone process can be restarted, this class provides a centralized place + * that applications can register and be called back from. + */ +class MSimTelephonyRegistry extends ITelephonyRegistryMSim.Stub { + private static final String TAG = "MSimTelephonyRegistry"; + private static final boolean DBG = false; + private static final boolean DBG_LOC = false; + + private static class Record { + String pkgForDebug; + + IBinder binder; + + IPhoneStateListener callback; + + int callerUid; + + int events; + + int subscription; + + @Override + public String toString() { + return "{pkgForDebug=" + pkgForDebug + " callerUid=" + callerUid + + " events=" + Integer.toHexString(events) + "}"; + } + } + + private final Context mContext; + + // access should be inside synchronized (mRecords) for these two fields + private final ArrayList mRemoveList = new ArrayList(); + private final ArrayList mRecords = new ArrayList(); + + private final IBatteryStats mBatteryStats; + + private int[] mCallState; + + private String[] mCallIncomingNumber; + + private ServiceState[] mServiceState; + + private SignalStrength[] mSignalStrength; + + private boolean[] mMessageWaiting; + + private boolean[] mCallForwarding; + + private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE; + + private int mDataConnectionState = TelephonyManager.DATA_UNKNOWN; + + private boolean mDataConnectionPossible = false; + + private String mDataConnectionReason = ""; + + private String mDataConnectionApn = ""; + + private ArrayList mConnectedApns; + + private LinkProperties mDataConnectionLinkProperties; + + private LinkCapabilities mDataConnectionLinkCapabilities; + + private Bundle[] mCellLocation; + + private int mDataConnectionNetworkType; + + private int mOtaspMode = ServiceStateTracker.OTASP_UNKNOWN; + + private ArrayList> mCellInfo = null; + + private int mDefaultSubscription = 0; + + static final int PHONE_STATE_PERMISSION_MASK = + PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR | + PhoneStateListener.LISTEN_CALL_STATE | + PhoneStateListener.LISTEN_DATA_ACTIVITY | + PhoneStateListener.LISTEN_DATA_CONNECTION_STATE | + PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR; + + private static final int MSG_USER_SWITCHED = 1; + + private final Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_USER_SWITCHED: { + Slog.d(TAG, "MSG_USER_SWITCHED userId=" + msg.arg1); + int numPhones = MSimTelephonyManager.getDefault().getPhoneCount(); + for (int sub = 0; sub < numPhones; sub++) { + MSimTelephonyRegistry.this.notifyCellLocation(mCellLocation[sub], sub); + } + break; + } + } + } + }; + + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (Intent.ACTION_USER_SWITCHED.equals(action)) { + mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED, + intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0)); + } + } + }; + + // we keep a copy of all of the state so we can send it out when folks + // register for it + // + // In these calls we call with the lock held. This is safe becasuse remote + // calls go through a oneway interface and local calls going through a + // handler before they get to app code. + + MSimTelephonyRegistry(Context context) { + CellLocation location = CellLocation.getEmpty(); + + mContext = context; + mBatteryStats = BatteryStatsService.getService(); + mConnectedApns = new ArrayList(); + + // Initialize default subscription to be used for single standby. + mDefaultSubscription = MSimTelephonyManager.getDefault().getDefaultSubscription(); + + int numPhones = MSimTelephonyManager.getDefault().getPhoneCount(); + mCallState = new int[numPhones]; + mCallIncomingNumber = new String[numPhones]; + mServiceState = new ServiceState[numPhones]; + mSignalStrength = new SignalStrength[numPhones]; + mMessageWaiting = new boolean[numPhones]; + mCallForwarding = new boolean[numPhones]; + mCellLocation = new Bundle[numPhones]; + mCellInfo = new ArrayList>(); + for (int i = 0; i < numPhones; i++) { + mCallState[i] = TelephonyManager.CALL_STATE_IDLE; + mCallIncomingNumber[i] = ""; + mServiceState[i] = new ServiceState(); + mSignalStrength[i] = new SignalStrength(); + mMessageWaiting[i] = false; + mCallForwarding[i] = false; + mCellLocation[i] = new Bundle(); + mCellInfo.add(i, null); + } + + // Note that location can be null for non-phone builds like + // like the generic one. + if (location != null) { + for (int i = 0; i < MSimTelephonyManager.getDefault().getPhoneCount(); i++) { + location.fillInNotifierBundle(mCellLocation[i]); + } + } + } + + public void systemReady() { + // Watch for interesting updates + final IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_USER_SWITCHED); + filter.addAction(Intent.ACTION_USER_REMOVED); + mContext.registerReceiver(mBroadcastReceiver, filter); + } + + @Override + public void listen(String pkgForDebug, IPhoneStateListener callback, int events, + boolean notifyNow, int subscription) { + int callerUid = UserHandle.getCallingUserId(); + int myUid = UserHandle.myUserId(); + if (DBG) { + Slog.d(TAG, "listen: E pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events) + + " myUid=" + myUid + + " callerUid=" + callerUid); + } + if (events != 0) { + /* Checks permission and throws Security exception */ + checkListenerPermission(events); + + synchronized (mRecords) { + // register + Record r = null; + find_and_add: { + IBinder b = callback.asBinder(); + final int N = mRecords.size(); + for (int i = 0; i < N; i++) { + r = mRecords.get(i); + if (b == r.binder) { + break find_and_add; + } + } + r = new Record(); + r.binder = b; + r.callback = callback; + r.pkgForDebug = pkgForDebug; + r.callerUid = callerUid; + r.subscription = subscription; + mRecords.add(r); + if (DBG) Slog.i(TAG, "listen: add new record=" + r); + } + int send = events & (events ^ r.events); + r.events = events; + if (notifyNow) { + if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) { + try { + r.callback.onServiceStateChanged( + new ServiceState(mServiceState[subscription])); + } catch (RemoteException ex) { + remove(r.binder); + } + } + if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) { + try { + int gsmSignalStrength = mSignalStrength[subscription] + .getGsmSignalStrength(); + r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1 + : gsmSignalStrength)); + } catch (RemoteException ex) { + remove(r.binder); + } + } + if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) { + try { + r.callback.onMessageWaitingIndicatorChanged( + mMessageWaiting[subscription]); + } catch (RemoteException ex) { + remove(r.binder); + } + } + if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) { + try { + r.callback.onCallForwardingIndicatorChanged( + mCallForwarding[subscription]); + } catch (RemoteException ex) { + remove(r.binder); + } + } + if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) { + try { + if (DBG_LOC) Slog.d(TAG, "listen: mCellLocation=" + + mCellLocation[subscription]); + r.callback.onCellLocationChanged( + new Bundle(mCellLocation[subscription])); + } catch (RemoteException ex) { + remove(r.binder); + } + } + if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) { + try { + r.callback.onCallStateChanged(mCallState[subscription], + mCallIncomingNumber[subscription]); + } catch (RemoteException ex) { + remove(r.binder); + } + } + if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { + try { + r.callback.onDataConnectionStateChanged(mDataConnectionState, + mDataConnectionNetworkType); + } catch (RemoteException ex) { + remove(r.binder); + } + } + if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) { + try { + r.callback.onDataActivity(mDataActivity); + } catch (RemoteException ex) { + remove(r.binder); + } + } + if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) { + try { + r.callback.onSignalStrengthsChanged(mSignalStrength[subscription]); + } catch (RemoteException ex) { + remove(r.binder); + } + } + if ((events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) { + try { + r.callback.onOtaspChanged(mOtaspMode); + } catch (RemoteException ex) { + remove(r.binder); + } + } + if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) { + try { + if (DBG_LOC) Slog.d(TAG, "listen: mCellInfo[" + subscription + "]=" + + mCellInfo.get(subscription)); + r.callback.onCellInfoChanged(mCellInfo.get(subscription)); + } catch (RemoteException ex) { + remove(r.binder); + } + } + } + } + } else { + remove(callback.asBinder()); + } + } + + private void remove(IBinder binder) { + synchronized (mRecords) { + final int recordCount = mRecords.size(); + for (int i = 0; i < recordCount; i++) { + if (mRecords.get(i).binder == binder) { + mRecords.remove(i); + return; + } + } + } + } + + public void notifyCallState(int state, String incomingNumber, int subscription) { + if (!checkNotifyPermission("notifyCallState()")) { + return; + } + synchronized (mRecords) { + mCallState[subscription] = state; + mCallIncomingNumber[subscription] = incomingNumber; + for (Record r : mRecords) { + if (((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) && + (r.subscription == subscription)) { + try { + r.callback.onCallStateChanged(state, incomingNumber); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + broadcastCallStateChanged(state, incomingNumber, subscription); + } + + public void notifyServiceState(ServiceState state, int subscription) { + if (!checkNotifyPermission("notifyServiceState()")){ + return; + } + Slog.i(TAG, "notifyServiceState: " + state); + synchronized (mRecords) { + mServiceState[subscription] = state; + for (Record r : mRecords) { + if (((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) && + (r.subscription == subscription)) { + try { + r.callback.onServiceStateChanged(new ServiceState(state)); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + broadcastServiceStateChanged(state, subscription); + } + + public void notifySignalStrength(SignalStrength signalStrength, int subscription) { + if (!checkNotifyPermission("notifySignalStrength()")) { + return; + } + synchronized (mRecords) { + mSignalStrength[subscription] = signalStrength; + for (Record r : mRecords) { + if (((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) && + (r.subscription == subscription)){ + try { + r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength)); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + if (((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) && + (r.subscription == subscription)) { + try { + int gsmSignalStrength = signalStrength.getGsmSignalStrength(); + r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1 + : gsmSignalStrength)); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + broadcastSignalStrengthChanged(signalStrength, subscription); + } + + public void notifyCellInfo(List cellInfo, int subscription) { + if (!checkNotifyPermission("notifyCellInfo()")) { + return; + } + + synchronized (mRecords) { + mCellInfo.set(subscription, cellInfo); + for (Record r : mRecords) { + if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO) + && r.subscription == subscription) { + try { + if (DBG_LOC) { + Slog.d(TAG, "notifyCellInfo: mCellInfo=" + cellInfo + " r=" + r); + } + r.callback.onCellInfoChanged(cellInfo); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + } + + public void notifyMessageWaitingChanged(boolean mwi, int subscription) { + if (!checkNotifyPermission("notifyMessageWaitingChanged()")) { + return; + } + synchronized (mRecords) { + mMessageWaiting[subscription] = mwi; + for (Record r : mRecords) { + if (((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) && + (r.subscription == subscription)) { + try { + r.callback.onMessageWaitingIndicatorChanged(mwi); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + } + + public void notifyCallForwardingChanged(boolean cfi, int subscription) { + if (!checkNotifyPermission("notifyCallForwardingChanged()")) { + return; + } + synchronized (mRecords) { + mCallForwarding[subscription] = cfi; + for (Record r : mRecords) { + if (((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) && + (r.subscription == subscription)) { + try { + r.callback.onCallForwardingIndicatorChanged(cfi); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + } + + public void notifyDataActivity(int state) { + if (!checkNotifyPermission("notifyDataActivity()" )) { + return; + } + synchronized (mRecords) { + mDataActivity = state; + for (Record r : mRecords) { + if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) { + try { + r.callback.onDataActivity(state); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + } + + public void notifyDataConnection(int state, boolean isDataConnectivityPossible, + String reason, String apn, String apnType, LinkProperties linkProperties, + LinkCapabilities linkCapabilities, int networkType, boolean roaming) { + if (!checkNotifyPermission("notifyDataConnection()" )) { + return; + } + if (DBG) { + Slog.i(TAG, "notifyDataConnection: state=" + state + " isDataConnectivityPossible=" + + isDataConnectivityPossible + " reason='" + reason + + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType + + " mRecords.size()=" + mRecords.size() + " mRecords=" + mRecords); + } + synchronized (mRecords) { + boolean modified = false; + if (state == TelephonyManager.DATA_CONNECTED) { + if (!mConnectedApns.contains(apnType)) { + mConnectedApns.add(apnType); + if (mDataConnectionState != state) { + mDataConnectionState = state; + modified = true; + } + } + } else { + if (mConnectedApns.remove(apnType)) { + if (mConnectedApns.isEmpty()) { + mDataConnectionState = state; + modified = true; + } else { + // leave mDataConnectionState as is and + // send out the new status for the APN in question. + } + } + } + mDataConnectionPossible = isDataConnectivityPossible; + mDataConnectionReason = reason; + mDataConnectionLinkProperties = linkProperties; + mDataConnectionLinkCapabilities = linkCapabilities; + if (mDataConnectionNetworkType != networkType) { + mDataConnectionNetworkType = networkType; + // need to tell registered listeners about the new network type + modified = true; + } + if (modified) { + if (DBG) { + Slog.d(TAG, "onDataConnectionStateChanged(" + mDataConnectionState + + ", " + mDataConnectionNetworkType + ")"); + } + for (Record r : mRecords) { + if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { + try { + r.callback.onDataConnectionStateChanged(mDataConnectionState, + mDataConnectionNetworkType); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + } + broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn, + apnType, linkProperties, linkCapabilities, roaming); + } + + public void notifyDataConnectionFailed(String reason, String apnType) { + if (!checkNotifyPermission("notifyDataConnectionFailed()")) { + return; + } + /* + * This is commented out because there is no onDataConnectionFailed callback + * in PhoneStateListener. There should be. + synchronized (mRecords) { + mDataConnectionFailedReason = reason; + final int N = mRecords.size(); + for (int i=N-1; i>=0; i--) { + Record r = mRecords.get(i); + if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_FAILED) != 0) { + // XXX + } + } + } + */ + broadcastDataConnectionFailed(reason, apnType); + } + + public void notifyCellLocation(Bundle cellLocation, int subscription) { + if (!checkNotifyPermission("notifyCellLocation()")) { + return; + } + synchronized (mRecords) { + mCellLocation[subscription] = cellLocation; + for (Record r : mRecords) { + if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) + && r.subscription == subscription) { + try { + if (DBG_LOC) { + Slog.d(TAG, "notifyCellLocation: mCellLocation=" + mCellLocation + + " r=" + r); + } + r.callback.onCellLocationChanged(new Bundle(cellLocation)); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + + } + } + handleRemoveListLocked(); + } + } + + public void notifyOtaspChanged(int otaspMode) { + if (!checkNotifyPermission("notifyOtaspChanged()" )) { + return; + } + synchronized (mRecords) { + mOtaspMode = otaspMode; + for (Record r : mRecords) { + if ((r.events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) { + try { + r.callback.onOtaspChanged(otaspMode); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + } + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump telephony.registry from from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); + return; + } + synchronized (mRecords) { + final int recordCount = mRecords.size(); + pw.println("last known state:"); + for (int i = 0; i < MSimTelephonyManager.getDefault().getPhoneCount(); i++) { + pw.println(" mCallState[" + i + "]=" + mCallState[i]); + pw.println(" mCallIncomingNumber[" + i + "]=" + mCallIncomingNumber[i]); + pw.println(" mServiceState[" + i + "]=" + mServiceState[i]); + pw.println(" mSignalStrength[" + i + "]=" + mSignalStrength[i]); + pw.println(" mMessageWaiting[" + i + "]=" + mMessageWaiting[i]); + pw.println(" mCallForwarding[" + i + "]=" + mCallForwarding[i]); + pw.println(" mCellLocation[" + i + "]=" + mCellLocation[i]); + pw.println(" mCellInfo[" + i + "]=" + mCellInfo.get(i)); + } + pw.println(" mDataActivity=" + mDataActivity); + pw.println(" mDataConnectionState=" + mDataConnectionState); + pw.println(" mDataConnectionPossible=" + mDataConnectionPossible); + pw.println(" mDataConnectionReason=" + mDataConnectionReason); + pw.println(" mDataConnectionApn=" + mDataConnectionApn); + pw.println(" mDataConnectionLinkProperties=" + mDataConnectionLinkProperties); + pw.println(" mDataConnectionLinkCapabilities=" + mDataConnectionLinkCapabilities); + pw.println(" mDataConnectionNetworkType=" + mDataConnectionNetworkType); + pw.println("registrations: count=" + recordCount); + for (Record r : mRecords) { + pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events)); + } + } + } + + // + // the legacy intent broadcasting + // + + private void broadcastServiceStateChanged(ServiceState state, int subscription) { + long ident = Binder.clearCallingIdentity(); + try { + mBatteryStats.notePhoneState(state.getState()); + } catch (RemoteException re) { + // Can't do much + } finally { + Binder.restoreCallingIdentity(ident); + } + + Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED); + Bundle data = new Bundle(); + state.fillInNotifierBundle(data); + intent.putExtras(data); + // Pass the subscription along with the intent. + intent.putExtra(MSimConstants.SUBSCRIPTION_KEY, subscription); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); + } + + private void broadcastSignalStrengthChanged(SignalStrength signalStrength, int subscription) { + long ident = Binder.clearCallingIdentity(); + try { + mBatteryStats.notePhoneSignalStrength(signalStrength); + } catch (RemoteException e) { + /* The remote entity disappeared, we can safely ignore the exception. */ + } finally { + Binder.restoreCallingIdentity(ident); + } + + Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED); + intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); + Bundle data = new Bundle(); + signalStrength.fillInNotifierBundle(data); + intent.putExtras(data); + intent.putExtra(MSimConstants.SUBSCRIPTION_KEY, subscription); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); + } + + private void broadcastCallStateChanged(int state, String incomingNumber, int subscription) { + long ident = Binder.clearCallingIdentity(); + try { + if (state == TelephonyManager.CALL_STATE_IDLE) { + mBatteryStats.notePhoneOff(); + } else { + mBatteryStats.notePhoneOn(); + } + } catch (RemoteException e) { + /* The remote entity disappeared, we can safely ignore the exception. */ + } finally { + Binder.restoreCallingIdentity(ident); + } + + Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED); + intent.putExtra(PhoneConstants.STATE_KEY, + DefaultPhoneNotifier.convertCallState(state).toString()); + if (!TextUtils.isEmpty(incomingNumber)) { + intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber); + } + intent.putExtra(MSimConstants.SUBSCRIPTION_KEY, subscription); + mContext.sendBroadcastAsUser(intent, UserHandle.ALL, + android.Manifest.permission.READ_PHONE_STATE); + } + + private void broadcastDataConnectionStateChanged(int state, + boolean isDataConnectivityPossible, + String reason, String apn, String apnType, LinkProperties linkProperties, + LinkCapabilities linkCapabilities, boolean roaming) { + // Note: not reporting to the battery stats service here, because the + // status bar takes care of that after taking into account all of the + // required info. + Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); + intent.putExtra(PhoneConstants.STATE_KEY, + DefaultPhoneNotifier.convertDataState(state).toString()); + if (!isDataConnectivityPossible) { + intent.putExtra(PhoneConstants.NETWORK_UNAVAILABLE_KEY, true); + } + if (reason != null) { + intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason); + } + if (linkProperties != null) { + intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties); + String iface = linkProperties.getInterfaceName(); + if (iface != null) { + intent.putExtra(PhoneConstants.DATA_IFACE_NAME_KEY, iface); + } + } + if (linkCapabilities != null) { + intent.putExtra(PhoneConstants.DATA_LINK_CAPABILITIES_KEY, linkCapabilities); + } + if (roaming) intent.putExtra(PhoneConstants.DATA_NETWORK_ROAMING_KEY, true); + + intent.putExtra(PhoneConstants.DATA_APN_KEY, apn); + intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); + } + + private void broadcastDataConnectionFailed(String reason, String apnType) { + Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED); + intent.putExtra(PhoneConstants.FAILURE_REASON_KEY, reason); + intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType); + intent.putExtra(MSimConstants.SUBSCRIPTION_KEY, + MSimTelephonyManager.getDefault().getPreferredDataSubscription()); + mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); + } + + private boolean checkNotifyPermission(String method) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + == PackageManager.PERMISSION_GRANTED) { + return true; + } + String msg = "Modify Phone State Permission Denial: " + method + " from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid(); + if (DBG) Slog.w(TAG, msg); + return false; + } + + private void checkListenerPermission(int events) { + if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_COARSE_LOCATION, null); + + } + + if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.ACCESS_COARSE_LOCATION, null); + + } + + if ((events & PHONE_STATE_PERMISSION_MASK) != 0) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.READ_PHONE_STATE, null); + } + } + + private void handleRemoveListLocked() { + if (mRemoveList.size() > 0) { + for (IBinder b: mRemoveList) { + remove(b); + } + mRemoveList.clear(); + } + } + + private boolean validateEventsAndUserLocked(Record r, int events) { + int foregroundUser; + long callingIdentity = Binder.clearCallingIdentity(); + boolean valid = false; + try { + foregroundUser = ActivityManager.getCurrentUser(); + valid = r.callerUid == foregroundUser && (r.events & events) != 0; + if (DBG | DBG_LOC) { + Slog.d(TAG, "validateEventsAndUserLocked: valid=" + valid + + " r.callerUid=" + r.callerUid + " foregroundUser=" + foregroundUser + + " r.events=" + r.events + " events=" + events); + } + } finally { + Binder.restoreCallingIdentity(callingIdentity); + } + return valid; + } +} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 63d5108503b03..707c8aab01ab5 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1,6 +1,9 @@ /* * Copyright (C) 2006 The Android Open Source Project * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc. + * Copyright (c) 2013 The Linux Foundation. All rights reserved. + * + * Not a Contribution. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -177,6 +180,7 @@ public void run() { CommonTimeManagementService commonTimeMgmtService = null; InputManagerService inputManager = null; TelephonyRegistry telephonyRegistry = null; + MSimTelephonyRegistry msimTelephonyRegistry = null; // Create a shared handler thread for UI within the system server. // This thread is used by at least the following components: @@ -247,6 +251,12 @@ public void run() { telephonyRegistry = new TelephonyRegistry(context); ServiceManager.addService("telephony.registry", telephonyRegistry); + if (android.telephony.MSimTelephonyManager.getDefault().isMultiSimEnabled()) { + Slog.i(TAG, "MSimTelephony Registry"); + msimTelephonyRegistry = new MSimTelephonyRegistry(context); + ServiceManager.addService("telephony.msim.registry", msimTelephonyRegistry); + } + Slog.i(TAG, "Scheduling Policy"); ServiceManager.addService(Context.SCHEDULING_POLICY_SERVICE, new SchedulingPolicyService()); @@ -987,6 +997,7 @@ public void run() { final DreamManagerService dreamyF = dreamy; final InputManagerService inputManagerF = inputManager; final TelephonyRegistry telephonyRegistryF = telephonyRegistry; + final MSimTelephonyRegistry msimTelephonyRegistryF = msimTelephonyRegistry; // We now tell the activity manager it is okay to run third party // code. It will call back into us once it has gotten to the state @@ -1124,6 +1135,11 @@ public void run() { } catch (Throwable e) { reportWtf("making TelephonyRegistry ready", e); } + try { + if (msimTelephonyRegistryF != null) msimTelephonyRegistryF.systemReady(); + } catch (Throwable e) { + reportWtf("making TelephonyRegistry ready", e); + } } }); diff --git a/services/java/com/android/server/power/ShutdownThread.java b/services/java/com/android/server/power/ShutdownThread.java index aee7a39dfd283..9760d72f94518 100644 --- a/services/java/com/android/server/power/ShutdownThread.java +++ b/services/java/com/android/server/power/ShutdownThread.java @@ -1,6 +1,9 @@ /* * Copyright (C) 2008 The Android Open Source Project * Copyright (C) 2013 The CyanogenMod Project + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Not a Contribution. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,8 +47,10 @@ import android.os.storage.IMountService; import android.os.storage.IMountShutdownObserver; import android.provider.Settings; +import android.telephony.MSimTelephonyManager; import com.android.internal.telephony.ITelephony; +import com.android.internal.telephony.msim.ITelephonyMSim; import android.util.Log; import android.view.WindowManager; @@ -493,10 +498,28 @@ public void run() { } try { - radioOff = phone == null || !phone.isRadioOn(); - if (!radioOff) { - Log.w(TAG, "Turning off radio..."); - phone.setRadio(false); + radioOff = true; + if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) { + final ITelephonyMSim mphone = ITelephonyMSim.Stub.asInterface( + ServiceManager.checkService("phone_msim")); + if (mphone != null) { + //radio off indication should be sent for both subscriptions + //in case of DSDS. + for (int i = 0; i < MSimTelephonyManager.getDefault(). + getPhoneCount(); i++) { + radioOff = radioOff && !mphone.isRadioOn(i); + if (mphone.isRadioOn(i)) { + Log.w(TAG, "Turning off radio on Subscription :" + i); + mphone.setRadio(false, i); + } + } + } + } else { + radioOff = phone == null || !phone.isRadioOn(); + if (!radioOff) { + Log.w(TAG, "Turning off radio..."); + phone.setRadio(false); + } } } catch (RemoteException ex) { Log.e(TAG, "RemoteException during radio shutdown", ex); @@ -519,7 +542,18 @@ public void run() { } if (!radioOff) { try { - radioOff = !phone.isRadioOn(); + boolean subRadioOff = true; + if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) { + final ITelephonyMSim mphone = ITelephonyMSim.Stub.asInterface( + ServiceManager.checkService("phone_msim")); + for (int i = 0; i < MSimTelephonyManager.getDefault(). + getPhoneCount(); i++) { + subRadioOff = subRadioOff && !mphone.isRadioOn(i); + } + radioOff = subRadioOff; + } else { + radioOff = !phone.isRadioOn(); + } } catch (RemoteException ex) { Log.e(TAG, "RemoteException during radio shutdown", ex); radioOff = true; diff --git a/telephony/java/android/telephony/MSimTelephonyManager.java b/telephony/java/android/telephony/MSimTelephonyManager.java new file mode 100644 index 0000000000000..bf1a999bfe38f --- /dev/null +++ b/telephony/java/android/telephony/MSimTelephonyManager.java @@ -0,0 +1,1134 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. + * + * Not a Contribution. + * + * 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.telephony; + +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.content.Context; +import android.os.Bundle; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemProperties; +import android.text.TextUtils; + +import com.android.internal.telephony.msim.ITelephonyMSim; +import com.android.internal.telephony.ITelephonyRegistryMSim; +import com.android.internal.telephony.msim.IPhoneSubInfoMSim; +import com.android.internal.telephony.MSimConstants; +import com.android.internal.telephony.PhoneConstants; +import com.android.internal.telephony.TelephonyProperties; + +import java.util.List; + +/** + * Provides access to information about the telephony services on + * the device. Applications can use the methods in this class to + * determine telephony services and states, as well as to access some + * types of subscriber information. Applications can also register + * a listener to receive notification of telephony state changes. + *

+ * You do not instantiate this class directly; instead, you retrieve + * a reference to an instance through + * {@link android.content.Context#getSystemService + * Context.getSystemService(Context.MSIM_TELEPHONY_SERVICE)}. + *

+ * Note that access to some telephony information is + * permission-protected. Your application cannot access the protected + * information unless it has the appropriate permissions declared in + * its manifest file. Where permissions apply, they are noted in the + * the methods through which you access the protected information. + * @hide + */ +public class MSimTelephonyManager { + /** @hide */ + private static Context sContext; + /** @hide */ + protected static ITelephonyRegistryMSim sRegistryMsim; + + protected static String multiSimConfig = + SystemProperties.get(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG); + + /** Enum indicating multisim variants + * DSDS - Dual SIM Dual Standby + * DSDA - Dual SIM Dual Active + * TSTS - Triple SIM Triple Standby + **/ + public enum MultiSimVariants { + DSDS, + DSDA, + TSTS, + UNKNOWN + }; + + /** @hide */ + public MSimTelephonyManager(Context context) { + if (sContext == null) { + Context appContext = context.getApplicationContext(); + if (appContext != null) { + sContext = appContext; + } else { + sContext = context; + } + + sRegistryMsim = ITelephonyRegistryMSim.Stub.asInterface(ServiceManager.getService( + "telephony.msim.registry")); + } + } + + /** @hide */ + private MSimTelephonyManager() { + } + + private static MSimTelephonyManager sInstance = new MSimTelephonyManager(); + + /** @hide + /* @deprecated - use getSystemService as described above */ + public static MSimTelephonyManager getDefault() { + return sInstance; + } + + /** {@hide} */ + public static MSimTelephonyManager from(Context context) { + return (MSimTelephonyManager) context.getSystemService(Context.MSIM_TELEPHONY_SERVICE); + } + + public boolean isMultiSimEnabled() { + return (multiSimConfig.equals("dsds") || multiSimConfig.equals("dsda") || + multiSimConfig.equals("tsts")); + } + + /** + * Returns the multi SIM variant + * Returns DSDS for Dual SIM Dual Standby + * Returns DSDA for Dual SIM Dual Active + * Returns TSTS for Triple SIM Triple Standby + * Returns UNKNOWN for others + */ + public MultiSimVariants getMultiSimConfiguration() { + if (multiSimConfig.equals("dsds")) { + return MultiSimVariants.DSDS; + } else if (multiSimConfig.equals("dsda")) { + return MultiSimVariants.DSDA; + } else if (multiSimConfig.equals("tsts")) { + return MultiSimVariants.TSTS; + } else { + return MultiSimVariants.UNKNOWN; + } + } + + + /** + * Returns the number of phones available. + * Returns 1 for Single standby mode (Single SIM functionality) + * Returns 2 for Dual standby mode.(Dual SIM functionality) + */ + public int getPhoneCount() { + int phoneCount = 1; + switch (getMultiSimConfiguration()) { + case DSDS: + case DSDA: + phoneCount = MSimConstants.MAX_PHONE_COUNT_DUAL_SIM; + break; + case TSTS: + phoneCount = MSimConstants.MAX_PHONE_COUNT_TRI_SIM; + break; + } + return phoneCount; + } + + /** + * Returns the software version number for the device, for example, + * the IMEI/SV for GSM phones. Return null if the software version is + * not available. + * + *

Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} + */ + public String getDeviceSoftwareVersion(int subscription) { + try { + return getMSimSubscriberInfo().getDeviceSvn(subscription); + } catch (RemoteException ex) { + return null; + } catch (NullPointerException ex) { + return null; + } + } + + /** + * Returns the unique device ID of a subscription, for example, the IMEI for + * GSM and the MEID for CDMA phones. Return null if device ID is not available. + * + *

Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} + * + * @param subscription of which deviceID is returned + */ + public String getDeviceId(int subscription) { + + try { + return getMSimSubscriberInfo().getDeviceId(subscription); + } catch (RemoteException ex) { + return null; + } catch (NullPointerException ex) { + return null; + } + } + + /** + * Returns a constant indicating the device phone type for a subscription. + * + * @see #PHONE_TYPE_NONE + * @see #PHONE_TYPE_GSM + * @see #PHONE_TYPE_CDMA + * + * @param subscription for which phone type is returned + * @hide + */ + public int getCurrentPhoneType(int subscription) { + + try{ + ITelephonyMSim telephony = getITelephonyMSim(); + if (telephony != null) { + return telephony.getActivePhoneType(subscription); + } else { + // This can happen when the ITelephonyMSim interface is not up yet. + return getPhoneTypeFromProperty(subscription); + } + } catch (RemoteException ex) { + // This shouldn't happen in the normal case, as a backup we + // read from the system property. + return getPhoneTypeFromProperty(subscription); + } catch (NullPointerException ex) { + // This shouldn't happen in the normal case, as a backup we + // read from the system property. + return getPhoneTypeFromProperty(subscription); + } + } + + /** + * Returns a constant indicating the device phone type. This + * indicates the type of radio used to transmit voice calls. + * + * @see #PHONE_TYPE_NONE + * @see #PHONE_TYPE_GSM + * @see #PHONE_TYPE_CDMA + * @see #PHONE_TYPE_SIP + * + * @param subscription for which phone type is returned + * @hide + */ + public int getPhoneType(int subscription) { + if (!TelephonyManager.getDefault().isVoiceCapable()) { + return TelephonyManager.PHONE_TYPE_NONE; + } + return getCurrentPhoneType(subscription); + } + + private int getPhoneTypeFromProperty(int subscription) { + String type = + getTelephonyProperty + (TelephonyProperties.CURRENT_ACTIVE_PHONE, subscription, null); + if (type != null) { + return (Integer.parseInt(type)); + } else { + return getPhoneTypeFromNetworkType(subscription); + } + } + + private int getPhoneTypeFromNetworkType(int subscription) { + // When the system property CURRENT_ACTIVE_PHONE, has not been set, + // use the system property for default network type. + // This is a fail safe, and can only happen at first boot. + String mode = getTelephonyProperty("ro.telephony.default_network", subscription, null); + if (mode != null) { + return TelephonyManager.getPhoneType(Integer.parseInt(mode)); + } + return TelephonyManager.PHONE_TYPE_NONE; + } + + // + // + // Current Network + // + // + + /** + * Returns the alphabetic name of current registered operator + * for a particular subscription. + *

+ * Availability: Only when user is registered to a network. Result may be + * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if + * on a CDMA network). + * @param subscription + */ + public String getNetworkOperatorName(int subscription) { + + return getTelephonyProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA, + subscription, ""); + } + + /** + * Returns the numeric name (MCC+MNC) of current registered operator + * for a particular subscription. + *

+ * Availability: Only when user is registered to a network. Result may be + * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if + * on a CDMA network). + * + * @param subscription + */ + public String getNetworkOperator(int subscription) { + + return getTelephonyProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, + subscription, ""); + } + + /** + * Returns true if the device is considered roaming on the current + * network for a subscription. + *

+ * Availability: Only when user registered to a network. + * + * @param subscription + */ + public boolean isNetworkRoaming(int subscription) { + return "true".equals(getTelephonyProperty(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING, + subscription, null)); + } + + /** + * Returns the ISO country code equivalent of the current registered + * operator's MCC (Mobile Country Code). + *

+ * Availability: Only when user is registered to a network. Result may be + * unreliable on CDMA networks (use {@link #getPhoneType()} to determine if + * on a CDMA network). + * + * @param subscription for which Network CountryIso is returned + * @hide + */ + public String getNetworkCountryIso(int subscription) { + return getTelephonyProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, + subscription, ""); + } + + /** + * Returns a constant indicating the radio technology (network type) + * currently in use on the device for data transmission for a subscription + * @return the network type + * + * @param subscription for which network type is returned + * + * @see #NETWORK_TYPE_UNKNOWN + * @see #NETWORK_TYPE_GPRS + * @see #NETWORK_TYPE_EDGE + * @see #NETWORK_TYPE_UMTS + * @see #NETWORK_TYPE_HSDPA + * @see #NETWORK_TYPE_HSUPA + * @see #NETWORK_TYPE_HSPA + * @see #NETWORK_TYPE_CDMA + * @see #NETWORK_TYPE_EVDO_0 + * @see #NETWORK_TYPE_EVDO_A + * @see #NETWORK_TYPE_EVDO_B + * @see #NETWORK_TYPE_1xRTT + * @see #NETWORK_TYPE_IDEN + * @see #NETWORK_TYPE_LTE + * @see #NETWORK_TYPE_EHRPD + * @see #NETWORK_TYPE_HSPAP + */ + public int getNetworkType(int subscription) { + try { + ITelephonyMSim iTelephony = getITelephonyMSim(); + if (iTelephony != null) { + return iTelephony.getNetworkType(subscription); + } else { + // This can happen when the ITelephony interface is not up yet. + return TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + } catch(RemoteException ex) { + // This shouldn't happen in the normal case + return TelephonyManager.NETWORK_TYPE_UNKNOWN; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + } + + /** + * Returns a constant indicating the radio technology (network type) + * currently in use on the device for data transmission. + * @return the network type + * + * @see #NETWORK_TYPE_UNKNOWN + * @see #NETWORK_TYPE_GPRS + * @see #NETWORK_TYPE_EDGE + * @see #NETWORK_TYPE_UMTS + * @see #NETWORK_TYPE_HSDPA + * @see #NETWORK_TYPE_HSUPA + * @see #NETWORK_TYPE_HSPA + * @see #NETWORK_TYPE_CDMA + * @see #NETWORK_TYPE_EVDO_0 + * @see #NETWORK_TYPE_EVDO_A + * @see #NETWORK_TYPE_EVDO_B + * @see #NETWORK_TYPE_1xRTT + * @see #NETWORK_TYPE_IDEN + * @see #NETWORK_TYPE_LTE + * @see #NETWORK_TYPE_EHRPD + * @see #NETWORK_TYPE_HSPAP + * @see #NETWORK_TYPE_TD_SCDMA + * + * @hide + */ + public int getDataNetworkType(int subscription) { + try{ + ITelephonyMSim telephony = getITelephonyMSim(); + if (telephony != null) { + return telephony.getDataNetworkType(subscription); + } else { + // This can happen when the ITelephonyMSim interface is not up yet. + return TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + } catch(RemoteException ex) { + // This shouldn't happen in the normal case + return TelephonyManager.NETWORK_TYPE_UNKNOWN; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + } + + /** + * Returns the NETWORK_TYPE_xxxx for voice + * + * @hide + */ + public int getVoiceNetworkType(int subscription) { + try{ + ITelephonyMSim telephony = getITelephonyMSim(); + if (telephony != null) { + return telephony.getVoiceNetworkType(subscription); + } else { + // This can happen when the ITelephonyMSim interface is not up yet. + return TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + } catch(RemoteException ex) { + // This shouldn't happen in the normal case + return TelephonyManager.NETWORK_TYPE_UNKNOWN; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + } + + /** + * Returns a string representation of the radio technology (network type) + * currently in use on the device. + * @param subscription for which network type is returned + * @return the name of the radio technology + * + * @hide pending API council review + */ + public String getNetworkTypeName(int subscription) { + return TelephonyManager.getNetworkTypeName(getNetworkType(subscription)); + } + + // + // + // SIM Card + // + // + + /** + * @return true if a ICC card is present for a subscription + * + * @param subscription for which icc card presence is checked + */ + public boolean hasIccCard(int subscription) { + + try { + return getITelephonyMSim().hasIccCard(subscription); + } catch (RemoteException ex) { + // Assume no ICC card if remote exception which shouldn't happen + return false; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return false; + } + } + + /** + * Returns a constant indicating the state of the + * device SIM card in a slot. + * + * @param slotId + * + * @see #SIM_STATE_UNKNOWN + * @see #SIM_STATE_ABSENT + * @see #SIM_STATE_PIN_REQUIRED + * @see #SIM_STATE_PUK_REQUIRED + * @see #SIM_STATE_NETWORK_LOCKED + * @see #SIM_STATE_READY + */ + public int getSimState(int slotId) { + String prop = + getTelephonyProperty(TelephonyProperties.PROPERTY_SIM_STATE, slotId, ""); + if ("ABSENT".equals(prop)) { + return TelephonyManager.SIM_STATE_ABSENT; + } + else if ("PIN_REQUIRED".equals(prop)) { + return TelephonyManager.SIM_STATE_PIN_REQUIRED; + } + else if ("PUK_REQUIRED".equals(prop)) { + return TelephonyManager.SIM_STATE_PUK_REQUIRED; + } + else if ("NETWORK_LOCKED".equals(prop)) { + return TelephonyManager.SIM_STATE_NETWORK_LOCKED; + } + else if ("READY".equals(prop)) { + return TelephonyManager.SIM_STATE_READY; + } + else { + return TelephonyManager.SIM_STATE_UNKNOWN; + } + } + + /** + * Returns the MCC+MNC (mobile country code + mobile network code) of the + * provider of the SIM. 5 or 6 decimal digits. + *

+ * Availability: SIM state must be {@link #SIM_STATE_READY} + * + * @see #getSimState + * + * @param subscription for which SimOperator is returned + * @hide + */ + public String getSimOperator(int subscription) { + return getTelephonyProperty(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, + subscription, ""); + } + + /** + * Returns the Service Provider Name (SPN). + *

+ * Availability: SIM state must be {@link #SIM_STATE_READY} + * + * @see #getSimState + * + * @param subscription for which SimOperatorName is returned + * @hide + */ + public String getSimOperatorName(int subscription) { + return getTelephonyProperty(TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, + subscription, ""); + } + + /** + * Returns the ISO country code equivalent for the SIM provider's country code. + * + * @param subscription for which SimCountryIso is returned + * @hide + */ + public String getSimCountryIso(int subscription) { + return getTelephonyProperty(TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY, + subscription, ""); + } + + /** + * Returns the serial number for the given subscription, if applicable. Return null if it is + * unavailable. + *

+ * Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} + */ + public String getSimSerialNumber(int subscription) { + try { + return getMSimSubscriberInfo().getIccSerialNumber(subscription); + } catch (RemoteException ex) { + return null; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return null; + } + } + + /** + * Return if the current radio is LTE on CDMA. This + * is a tri-state return value as for a period of time + * the mode may be unknown. + * + * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE} + * or {@link Phone#LTE_ON_CDMA_TRUE} + * + * @hide + */ + public int getLteOnCdmaMode(int subscription) { + try { + return getITelephonyMSim().getLteOnCdmaMode(subscription); + } catch (RemoteException ex) { + // Assume no ICC card if remote exception which shouldn't happen + return PhoneConstants.LTE_ON_CDMA_UNKNOWN; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return PhoneConstants.LTE_ON_CDMA_UNKNOWN; + } + } + + // + // + // Subscriber Info + // + // + + /** + * Returns the unique subscriber ID, for example, the IMSI for a GSM phone + * for a subscription. + * Return null if it is unavailable. + *

+ * Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} + * + * @param subscription whose subscriber id is returned + */ + public String getSubscriberId(int subscription) { + try { + return getMSimSubscriberInfo().getSubscriberId(subscription); + } catch (RemoteException ex) { + return null; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return null; + } + } + + /** + * Returns the phone number string for line 1, for example, the MSISDN + * for a GSM phone for a particular subscription. Return null if it is unavailable. + *

+ * Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} + * + * @param subscription whose phone number for line 1 is returned + */ + public String getLine1Number(int subscription) { + try { + return getMSimSubscriberInfo().getLine1Number(subscription); + } catch (RemoteException ex) { + return null; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return null; + } + } + + /** + * Returns the alphabetic identifier associated with the line 1 number + * for a subscription. + * Return null if it is unavailable. + *

+ * Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} + * @param subscription whose alphabetic identifier associated with line 1 is returned + * @hide + * nobody seems to call this. + */ + public String getLine1AlphaTag(int subscription) { + try { + return getMSimSubscriberInfo().getLine1AlphaTag(subscription); + } catch (RemoteException ex) { + return null; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return null; + } + } + + /** + * Returns the MSISDN string. + * for a GSM phone. Return null if it is unavailable. + *

+ * Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} + * + * @param subscription for which msisdn is returned + * @hide + */ + public String getMsisdn(int subscription) { + try { + return getMSimSubscriberInfo().getMsisdn(subscription); + } catch (RemoteException ex) { + return null; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return null; + } + } + + /** + * Returns the voice mail number for a subscription. + * Return null if it is unavailable. + *

+ * Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} + * @param subscription whose voice mail number is returned + */ + public String getVoiceMailNumber(int subscription) { + try { + return getMSimSubscriberInfo().getVoiceMailNumber(subscription); + } catch (RemoteException ex) { + return null; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return null; + } + } + + /** + * Returns the complete voice mail number. Return null if it is unavailable. + *

+ * Requires Permission: + * {@link android.Manifest.permission#CALL_PRIVILEGED CALL_PRIVILEGED} + * + * @param subscription + * @hide + */ + public String getCompleteVoiceMailNumber(int subscription) { + try { + return getMSimSubscriberInfo().getCompleteVoiceMailNumber(subscription); + } catch (RemoteException ex) { + return null; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return null; + } + } + + + /** + * Returns the voice mail count for a subscription. Return 0 if unavailable. + *

+ * Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} + * @param subscription whose voice message count is returned + * @hide + */ + public int getVoiceMessageCount(int subscription) { + try { + return getITelephonyMSim().getVoiceMessageCount(subscription); + } catch (RemoteException ex) { + return 0; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return 0; + } + } + + /** + * Retrieves the alphabetic identifier associated with the voice + * mail number for a subscription. + *

+ * Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} + * @param subscription whose alphabetic identifier associated with the + * voice mail number is returned + */ + public String getVoiceMailAlphaTag(int subscription) { + try { + return getMSimSubscriberInfo().getVoiceMailAlphaTag(subscription); + } catch (RemoteException ex) { + return null; + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + return null; + } + } + + /** + * @hide + */ + protected IPhoneSubInfoMSim getMSimSubscriberInfo() { + // get it each time because that process crashes a lot + return IPhoneSubInfoMSim.Stub.asInterface(ServiceManager.getService("iphonesubinfo_msim")); + } + + /** + * Returns a constant indicating the call state (cellular) on the device + * for a subscription. + * + * @param subscription whose call state is returned + */ + public int getCallState(int subscription) { + try { + return getITelephonyMSim().getCallState(subscription); + } catch (RemoteException ex) { + // the phone process is restarting. + return TelephonyManager.CALL_STATE_IDLE; + } catch (NullPointerException ex) { + // the phone process is restarting. + return TelephonyManager.CALL_STATE_IDLE; + } + } + + /** + * Returns a constant indicating the type of activity on a data connection + * (cellular). + * + * @see #DATA_ACTIVITY_NONE + * @see #DATA_ACTIVITY_IN + * @see #DATA_ACTIVITY_OUT + * @see #DATA_ACTIVITY_INOUT + * @see #DATA_ACTIVITY_DORMANT + */ + public int getDataActivity() { + try { + return getITelephonyMSim().getDataActivity(); + } catch (RemoteException ex) { + // the phone process is restarting. + return TelephonyManager.DATA_ACTIVITY_NONE; + } catch (NullPointerException ex) { + // the phone process is restarting. + return TelephonyManager.DATA_ACTIVITY_NONE; + } + } + + /** + * Returns a constant indicating the current data connection state + * (cellular). + * + * @see #DATA_DISCONNECTED + * @see #DATA_CONNECTING + * @see #DATA_CONNECTED + * @see #DATA_SUSPENDED + */ + public int getDataState() { + try { + return getITelephonyMSim().getDataState(); + } catch (RemoteException ex) { + // the phone process is restarting. + return TelephonyManager.DATA_DISCONNECTED; + } catch (NullPointerException ex) { + return TelephonyManager.DATA_DISCONNECTED; + } + } + + private ITelephonyMSim getITelephonyMSim() { + return ITelephonyMSim.Stub.asInterface(ServiceManager.getService( + Context.MSIM_TELEPHONY_SERVICE)); + } + + // + // + // PhoneStateListener + // + // + + /** + * Registers a listener object to receive notification of changes + * in specified telephony states. + *

+ * To register a listener, pass a {@link PhoneStateListener} + * and specify at least one telephony state of interest in + * the events argument. + * + * At registration, and when a specified telephony state + * changes, the telephony manager invokes the appropriate + * callback method on the listener object and passes the + * current (udpated) values. + *

+ * To unregister a listener, pass the listener object and set the + * events argument to + * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0). + * + * @param listener The {@link PhoneStateListener} object to register + * (or unregister) + * @param events The telephony state(s) of interest to the listener, + * as a bitwise-OR combination of {@link PhoneStateListener} + * LISTEN_ flags. + */ + public void listen(PhoneStateListener listener, int events) { + String pkgForDebug = sContext != null ? sContext.getPackageName() : ""; + try { + Boolean notifyNow = (getITelephonyMSim() != null); + sRegistryMsim.listen(pkgForDebug, listener.callback, events, notifyNow, + listener.mSubscription); + } catch (RemoteException ex) { + // system process dead + } catch (NullPointerException ex) { + // system process dead + } + } + + /** + * Returns the CDMA ERI icon index to display for a subscription + * + * @hide + */ + public int getCdmaEriIconIndex(int subscription) { + try { + return getITelephonyMSim().getCdmaEriIconIndex(subscription); + } catch (RemoteException ex) { + // the phone process is restarting. + return -1; + } catch (NullPointerException ex) { + return -1; + } + } + + /** + * Returns the CDMA ERI icon mode for a subscription. + * 0 - ON + * 1 - FLASHING + * + * @hide + */ + public int getCdmaEriIconMode(int subscription) { + try { + return getITelephonyMSim().getCdmaEriIconMode(subscription); + } catch (RemoteException ex) { + // the phone process is restarting. + return -1; + } catch (NullPointerException ex) { + return -1; + } + } + + /** + * Returns the CDMA ERI text, of a subscription + * + * @hide + */ + public String getCdmaEriText(int subscription) { + try { + return getITelephonyMSim().getCdmaEriText(subscription); + } catch (RemoteException ex) { + // the phone process is restarting. + return null; + } catch (NullPointerException ex) { + return null; + } + } + + /** + * Returns all observed cell information of the device. + * + * @return List of CellInfo or null if info unavailable + * for subscription. + * + *

Requires Permission: + * (@link android.Manifest.permission#ACCESS_COARSE_UPDATES} + * + * @hide pending API review + */ + public List getAllCellInfo() { + try { + return getITelephonyMSim().getAllCellInfo(); + } catch (RemoteException ex) { + return null; + } catch (NullPointerException ex) { + return null; + } + } + + /** + * Sets the telephony property with the value specified. + * + * @hide + */ + public static void setTelephonyProperty(String property, int index, String value) { + String propVal = ""; + String p[] = null; + String prop = SystemProperties.get(property); + + if (prop != null) { + p = prop.split(","); + } + + if (index < 0) return; + + for (int i = 0; i < index; i++) { + String str = ""; + if ((p != null) && (i < p.length)) { + str = p[i]; + } + propVal = propVal + str + ","; + } + + propVal = propVal + value; + if (p != null) { + for (int i = index+1; i < p.length; i++) { + propVal = propVal + "," + p[i]; + } + } + SystemProperties.set(property, propVal); + } + + /** + * Gets the telephony property. + * + * @hide + */ + public static String getTelephonyProperty(String property, int index, String defaultVal) { + String propVal = null; + String prop = SystemProperties.get(property); + + if ((prop != null) && (prop.length() > 0)) { + String values[] = prop.split(","); + if ((index >= 0) && (index < values.length) && (values[index] != null)) { + propVal = values[index]; + } + } + return propVal == null ? defaultVal : propVal; + } + + /** + * Returns Default subscription. + * Returns default value 0, if default subscription is not available + */ + public int getDefaultSubscription() { + try { + return getITelephonyMSim().getDefaultSubscription(); + } catch (RemoteException ex) { + return MSimConstants.DEFAULT_SUBSCRIPTION; + } catch (NullPointerException ex) { + return MSimConstants.DEFAULT_SUBSCRIPTION; + } + } + + /** + * Returns the designated data subscription. + */ + public int getPreferredDataSubscription() { + try { + return getITelephonyMSim().getPreferredDataSubscription(); + } catch (RemoteException ex) { + return MSimConstants.DEFAULT_SUBSCRIPTION; + } catch (NullPointerException ex) { + return MSimConstants.DEFAULT_SUBSCRIPTION; + } + } + + /** + * Sets the designated data subscription. + */ + public boolean setPreferredDataSubscription(int subscription) { + try { + return getITelephonyMSim().setPreferredDataSubscription(subscription); + } catch (RemoteException ex) { + return false; + } catch (NullPointerException ex) { + return false; + } + } + + /** + * Returns the preferred voice subscription. + */ + public int getPreferredVoiceSubscription() { + try { + return getITelephonyMSim().getPreferredVoiceSubscription(); + } catch (RemoteException ex) { + return MSimConstants.DEFAULT_SUBSCRIPTION; + } catch (NullPointerException ex) { + return MSimConstants.DEFAULT_SUBSCRIPTION; + } + } + + /** + * Convenience function for retrieving a value from the secure settings + * value list as an integer. Note that internally setting values are + * always stored as strings; this function converts the string to an + * integer for you. + *

+ * This version does not take a default value. If the setting has not + * been set, or the string value is not a number, + * it throws {@link SettingNotFoundException}. + * + * @param cr The ContentResolver to access. + * @param name The name of the setting to retrieve. + * @param index The index of the list + * + * @throws SettingNotFoundException Thrown if a setting by the given + * name can't be found or the setting value is not an integer. + * + * @return The value at the given index of settings. + * @hide + */ + public static int getIntAtIndex(android.content.ContentResolver cr, + String name, int index) + throws android.provider.Settings.SettingNotFoundException { + String v = android.provider.Settings.Global.getString(cr, name); + if (v != null) { + String valArray[] = v.split(","); + if ((index >= 0) && (index < valArray.length) && (valArray[index] != null)) { + try { + return Integer.parseInt(valArray[index]); + } catch (NumberFormatException e) { + //Log.e(TAG, "Exception while parsing Integer: ", e); + } + } + } + throw new android.provider.Settings.SettingNotFoundException(name); + } + + /** + * Convenience function for updating settings value as coma separated + * integer values. This will either create a new entry in the table if the + * given name does not exist, or modify the value of the existing row + * with that name. Note that internally setting values are always + * stored as strings, so this function converts the given value to a + * string before storing it. + * + * @param cr The ContentResolver to access. + * @param name The name of the setting to modify. + * @param index The index of the list + * @param value The new value for the setting to be added to the list. + * @return true if the value was set, false on database errors + * @hide + */ + public static boolean putIntAtIndex(android.content.ContentResolver cr, + String name, int index, int value) { + String data = ""; + String valArray[] = null; + String v = android.provider.Settings.Global.getString(cr, name); + + if (v != null) { + valArray = v.split(","); + } + + // Copy the elements from valArray till index + for (int i = 0; i < index; i++) { + String str = ""; + if ((valArray != null) && (i < valArray.length)) { + str = valArray[i]; + } + data = data + str + ","; + } + + data = data + value; + + // Copy the remaining elements from valArray if any. + if (valArray != null) { + for (int i = index+1; i < valArray.length; i++) { + data = data + "," + valArray[i]; + } + } + return android.provider.Settings.Global.putString(cr, name, data); + } +} diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index 3ae210636f84f..e7ddd9cd7e69a 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -1,5 +1,8 @@ /* * Copyright (C) 2006 The Android Open Source Project + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Not a Contribution. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +39,7 @@ import android.telephony.Rlog; import android.util.SparseIntArray; +import static com.android.internal.telephony.MSimConstants.SUBSCRIPTION_KEY; import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY; import static com.android.internal.telephony.TelephonyProperties.PROPERTY_IDP_STRING; import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY; @@ -166,6 +170,12 @@ public static String getNumberFromIntent(Intent intent, Context context) { // TODO: We don't check for SecurityException here (requires // CALL_PRIVILEGED permission). if (scheme.equals("voicemail")) { + if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) { + int subscription = intent.getIntExtra(SUBSCRIPTION_KEY, + MSimTelephonyManager.getDefault().getDefaultSubscription()); + return MSimTelephonyManager.getDefault() + .getCompleteVoiceMailNumber(subscription); + } return TelephonyManager.getDefault().getCompleteVoiceMailNumber(); } @@ -1831,7 +1841,13 @@ public static boolean isVoiceMailNumber(String number) { String vmNumber; try { - vmNumber = TelephonyManager.getDefault().getVoiceMailNumber(); + if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) { + int subscription = MSimTelephonyManager.getDefault() + .getPreferredVoiceSubscription(); + vmNumber = MSimTelephonyManager.getDefault().getVoiceMailNumber(subscription); + } else { + vmNumber = TelephonyManager.getDefault().getVoiceMailNumber(); + } } catch (SecurityException ex) { return false; } diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java index ff77fc012f5ce..da9bdfb96285e 100644 --- a/telephony/java/android/telephony/PhoneStateListener.java +++ b/telephony/java/android/telephony/PhoneStateListener.java @@ -1,5 +1,8 @@ /* * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. + * + * Not a Contribution. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +27,7 @@ import android.telephony.CellLocation; import android.telephony.CellInfo; import android.telephony.Rlog; +import android.telephony.MSimTelephonyManager; import com.android.internal.telephony.IPhoneStateListener; @@ -165,7 +169,22 @@ public class PhoneStateListener { */ public static final int LISTEN_CELL_INFO = 0x00000400; + /** + * Subscription used to listen to the phone state changes + * @hide + */ + protected int mSubscription = 0; + public PhoneStateListener() { + // If subscription is not passed set the default subscription. + mSubscription = MSimTelephonyManager.getDefault().getDefaultSubscription(); + } + + /** + * @hide + */ + public PhoneStateListener(int subscription) { + mSubscription = subscription; } /** diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 4360e9df010f1..333a078d29f10 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -1,5 +1,8 @@ /* * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Not a Contribution. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +27,8 @@ import android.os.ServiceManager; import android.os.SystemProperties; import android.telephony.Rlog; +import android.provider.Settings; +import android.provider.Settings.SettingNotFoundException; import com.android.internal.telephony.IPhoneSubInfo; import com.android.internal.telephony.ITelephony; @@ -531,7 +536,8 @@ public static int getLteOnGsmModeStatic() { * on a CDMA network). */ public String getNetworkOperatorName() { - return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ALPHA); + return getTelephonyProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA, + getDefaultSubscription(), ""); } /** @@ -542,7 +548,8 @@ public String getNetworkOperatorName() { * on a CDMA network). */ public String getNetworkOperator() { - return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC); + return getTelephonyProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, + getDefaultSubscription(), ""); } /** @@ -552,7 +559,8 @@ public String getNetworkOperator() { * Availability: Only when user registered to a network. */ public boolean isNetworkRoaming() { - return "true".equals(SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING)); + return "true".equals(getTelephonyProperty(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING, + getDefaultSubscription(), "false")); } /** @@ -564,7 +572,35 @@ public boolean isNetworkRoaming() { * on a CDMA network). */ public String getNetworkCountryIso() { - return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY); + return getTelephonyProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, + getDefaultSubscription(), ""); + } + + /** + * Gets the telephony Default Subscription. + * + * @hide + */ + public static int getDefaultSubscription() { + return SystemProperties.getInt(TelephonyProperties.PROPERTY_DEFAULT_SUBSCRIPTION, 0); + } + + + /** + * Gets the telephony property. + * + * @hide + */ + public static String getTelephonyProperty(String property, int index, String defaultVal) { + String propVal = null; + String prop = SystemProperties.get(property); + if ((prop != null) && (prop.length() > 0)) { + String values[] = prop.split(","); + if ((index >= 0) && (index < values.length) && (values[index] != null)) { + propVal = values[index]; + } + } + return propVal == null ? defaultVal : propVal; } /** Network type is unknown */ @@ -840,7 +876,8 @@ public boolean hasIccCard() { * @see #SIM_STATE_CARD_IO_ERROR */ public int getSimState() { - String prop = SystemProperties.get(TelephonyProperties.PROPERTY_SIM_STATE); + String prop = getTelephonyProperty(TelephonyProperties.PROPERTY_SIM_STATE, + getDefaultSubscription(), ""); if ("ABSENT".equals(prop)) { return SIM_STATE_ABSENT; } @@ -873,7 +910,8 @@ else if ("CARD_IO_ERROR".equals(prop)) { * @see #getSimState */ public String getSimOperator() { - return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC); + return getTelephonyProperty(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, + getDefaultSubscription(), ""); } /** @@ -884,14 +922,16 @@ public String getSimOperator() { * @see #getSimState */ public String getSimOperatorName() { - return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA); + return getTelephonyProperty(TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, + getDefaultSubscription(), ""); } /** * Returns the ISO country code equivalent for the SIM provider's country code. */ public String getSimCountryIso() { - return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY); + return getTelephonyProperty(TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY, + getDefaultSubscription(), ""); } /** diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistryMSim.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistryMSim.aidl new file mode 100644 index 0000000000000..c8bbdecf2f638 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistryMSim.aidl @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. + * + * Not a Contribution. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.telephony; + +import android.content.Intent; +import android.net.LinkProperties; +import android.net.LinkCapabilities; +import android.os.Bundle; +import android.telephony.CellInfo; +import android.telephony.ServiceState; +import android.telephony.SignalStrength; +import com.android.internal.telephony.IPhoneStateListener; + +interface ITelephonyRegistryMSim { + void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow, + int subscription); + + void notifyCallState(int state, String incomingNumber, in int subscription); + void notifyServiceState(in ServiceState state, in int subscription); + void notifySignalStrength(in SignalStrength signalStrength, in int subscription); + void notifyMessageWaitingChanged(boolean mwi, in int subscription); + void notifyCallForwardingChanged(boolean cfi, in int subscription); + void notifyDataActivity(int state); + void notifyDataConnection(int state, boolean isDataConnectivityPossible, + String reason, String apn, String apnType, in LinkProperties linkProperties, + in LinkCapabilities linkCapabilities, int networkType, boolean roaming); + void notifyDataConnectionFailed(String reason, String apnType); + void notifyCellLocation(in Bundle cellLocation, in int subscription); + void notifyOtaspChanged(in int otaspMode); + void notifyCellInfo(in List cellInfo, in int subscription); +} diff --git a/telephony/java/com/android/internal/telephony/MSimConstants.java b/telephony/java/com/android/internal/telephony/MSimConstants.java new file mode 100644 index 0000000000000..e9b77d7e888a0 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/MSimConstants.java @@ -0,0 +1,60 @@ +/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +package com.android.internal.telephony; + +public class MSimConstants { + + public static final int DEFAULT_SUBSCRIPTION = 0; + + public static final int RIL_CARD_MAX_APPS = 8; + + public static final int DEFAULT_CARD_INDEX = 0; + + public static final int MAX_PHONE_COUNT_SINGLE_SIM = 1; + + public static final int MAX_PHONE_COUNT_DUAL_SIM = 2; + + public static final int MAX_PHONE_COUNT_TRI_SIM = 3; + + public static final String SUBSCRIPTION_KEY = "subscription"; + + public static final int SUB1 = 0; + public static final int SUB2 = 1; + public static final int SUB3 = 2; + + public static final int EVENT_SUBSCRIPTION_ACTIVATED = 500; + public static final int EVENT_SUBSCRIPTION_DEACTIVATED = 501; + + public enum CardUnavailableReason { + REASON_CARD_REMOVED, + REASON_RADIO_UNAVAILABLE, + REASON_SIM_REFRESH_RESET + }; +} diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index f0f2c25f16f6f..4470f4dfbbb51 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -1,6 +1,8 @@ /* * Copyright (C) 2006 The Android Open Source Project - * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + *Not a Contribution. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -65,6 +67,7 @@ class C */ int SS_MODIFIED_TO_DIAL = 23; /* SS request modified to DIAL */ int SS_MODIFIED_TO_USSD = 24; /* SS request modified to USSD */ int SS_MODIFIED_TO_SS = 25; /* SS request modified to different SS request */ + int SUBSCRIPTION_NOT_SUPPORTED = 26; /* Subscription not supported */ /* NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE */ int NETWORK_MODE_WCDMA_PREF = 0; /* GSM/WCDMA (WCDMA preferred) */ @@ -281,6 +284,10 @@ class C */ int RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE = 110; int RIL_REQUEST_IMS_REGISTRATION_STATE = 111; int RIL_REQUEST_IMS_SEND_SMS = 112; + int RIL_REQUEST_SET_UICC_SUBSCRIPTION = 114; + int RIL_REQUEST_SET_DATA_SUBSCRIPTION = 115; + int RIL_REQUEST_GET_UICC_SUBSCRIPTION = 116; + int RIL_REQUEST_GET_DATA_SUBSCRIPTION = 117; int RIL_UNSOL_RESPONSE_BASE = 1000; int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000; int RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED = 1001; @@ -323,6 +330,7 @@ class C */ int RIL_UNSOL_TETHERED_MODE_STATE_CHANGED = 1038; int RIL_UNSOL_ON_SS = 1039; int RIL_UNSOL_STK_CC_ALPHA_NOTIFY = 1040; + int RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED = 1041; int RIL_UNSOL_STK_SEND_SMS_RESULT = 11002; /* Samsung STK */ } diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index 471cc6bad1530..0062b7edeb5a3 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -1,5 +1,8 @@ /* * Copyright (C) 2006 The Android Open Source Project + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Not a Contribution. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -214,4 +217,15 @@ public interface TelephonyProperties * Type: boolean ( true = alpha display enabled, false = alpha display disabled) */ static final String PROPERTY_ALPHA_USRCNF = "persist.atel.noalpha.usrcnf"; + + /** + * Property to set multi sim feature. + * Type: String(dsds, dsda) + */ + static final String PROPERTY_MULTI_SIM_CONFIG = "persist.multisim.config"; + + /** + * Property to store default subscription. + */ + static final String PROPERTY_DEFAULT_SUBSCRIPTION = "persist.default.subscription"; } diff --git a/telephony/java/com/android/internal/telephony/msim/IPhoneSubInfoMSim.aidl b/telephony/java/com/android/internal/telephony/msim/IPhoneSubInfoMSim.aidl new file mode 100644 index 0000000000000..693a4630df958 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/msim/IPhoneSubInfoMSim.aidl @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Not a Contribution. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.android.internal.telephony.msim; + +/** + * Interface used to retrieve various phone-related subscriber information. + * {@hide} + */ +interface IPhoneSubInfoMSim { + + /** + * Retrieves the unique device ID of a subscription for the device, e.g., IMEI + * for GSM phones. + */ + String getDeviceId(int subscription); + + /** + * Retrieves the software version number of a subscription for the device, e.g., IMEI/SV + * for GSM phones. + */ + String getDeviceSvn(int subscription); + + /** + * Retrieves the unique subscriber ID of a given subscription, e.g., IMSI for GSM phones. + */ + String getSubscriberId(int subscription); + + /** + * Retrieves the serial number of a given subscription. + */ + String getIccSerialNumber(int subscription); + + /** + * Retrieves the phone number string for line 1 of a subcription. + */ + String getLine1Number(int subscription); + + /** + * Retrieves the alpha identifier for line 1 of a subscription. + */ + String getLine1AlphaTag(int subscription); + + /** + * Retrieves the Msisdn of a subscription. + */ + String getMsisdn(int subscription); + + /** + * Retrieves the voice mail number of a given subscription. + */ + String getVoiceMailNumber(int subscription); + + /** + * Retrieves the complete voice mail number for particular subscription + */ + String getCompleteVoiceMailNumber(int subscription); + + /** + * Retrieves the alpha identifier associated with the voice mail number + * of a subscription. + */ + String getVoiceMailAlphaTag(int subscription); + +} diff --git a/telephony/java/com/android/internal/telephony/msim/ITelephonyMSim.aidl b/telephony/java/com/android/internal/telephony/msim/ITelephonyMSim.aidl new file mode 100644 index 0000000000000..a6add360ee44d --- /dev/null +++ b/telephony/java/com/android/internal/telephony/msim/ITelephonyMSim.aidl @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved. + * + * Not a Contribution. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.telephony.msim; + +import android.os.Bundle; +import java.util.List; +import android.telephony.NeighboringCellInfo; +import android.telephony.CellInfo; + +/** + * Interface used to interact with the phone. Mostly this is used by the + * TelephonyManager class. A few places are still using this directly. + * Please clean them up if possible and use TelephonyManager instead. + * + * {@hide} + */ +interface ITelephonyMSim { + /** + * Dial a number. This doesn't place the call. It displays + * the Dialer screen for that subscription. + * @param number the number to be dialed. If null, this + * would display the Dialer screen with no number pre-filled. + * @param subscription user preferred subscription. + */ + void dial(String number, int subscription); + + /** + * Place a call to the specified number on particular subscription. + * @param number the number to be called. + * @param subscription user preferred subscription. + */ + void call(String number, int subscription); + + /** + * If there is currently a call in progress, show the call screen. + * The DTMF dialpad may or may not be visible initially, depending on + * whether it was up when the user last exited the InCallScreen. + * + * @return true if the call screen was shown. + */ + boolean showCallScreen(); + + /** + * Variation of showCallScreen() that also specifies whether the + * DTMF dialpad should be initially visible when the InCallScreen + * comes up. + * + * @param showDialpad if true, make the dialpad visible initially, + * otherwise hide the dialpad initially. + * @return true if the call screen was shown. + * + * @see showCallScreen + */ + boolean showCallScreenWithDialpad(boolean showDialpad); + + /** + * End call on particular subscription or go to the Home screen + * @param subscription user preferred subscription. + * @return whether it hung up + */ + boolean endCall(int subscription); + + /** + * Answer the currently-ringing call on particular subscription. + * + * If there's already a current active call, that call will be + * automatically put on hold. If both lines are currently in use, the + * current active call will be ended. + * + * TODO: provide a flag to let the caller specify what policy to use + * if both lines are in use. (The current behavior is hardwired to + * "answer incoming, end ongoing", which is how the CALL button + * is specced to behave.) + * + * TODO: this should be a oneway call (especially since it's called + * directly from the key queue thread). + * + * @param subscription user preferred subscription. + */ + void answerRingingCall(int subscription); + + /** + * Silence the ringer if an incoming call is currently ringing. + * (If vibrating, stop the vibrator also.) + * + * It's safe to call this if the ringer has already been silenced, or + * even if there's no incoming call. (If so, this method will do nothing.) + * + * TODO: this should be a oneway call too (see above). + * (Actually *all* the methods here that return void can + * probably be oneway.) + */ + void silenceRinger(); + + /** + * Check if a particular subscription has an active or holding call + * + * @param subscription user preferred subscription. + * @return true if the phone state is OFFHOOK. + */ + boolean isOffhook(int subscription); + + /** + * Check if an incoming phone call is ringing or call waiting + * on a particular subscription. + * + * @param subscription user preferred subscription. + * @return true if the phone state is RINGING. + */ + boolean isRinging(int subscription); + + /** + * Check if the phone is idle on a particular subscription. + * + * @param subscription user preferred subscription. + * @return true if the phone state is IDLE. + */ + boolean isIdle(int subscription); + + /** + * Check to see if the radio is on or not on particular subscription. + * @param subscription user preferred subscription. + * @return returns true if the radio is on. + */ + boolean isRadioOn(int subscription); + + /** + * Check if the SIM pin lock is enable + * for particular subscription. + * @param subscription user preferred subscription. + * @return true if the SIM pin lock is enabled. + */ + boolean isSimPinEnabled(int subscription); + + /** + * Cancels the missed calls notification on particular subscription. + * @param subscription user preferred subscription. + */ + void cancelMissedCallsNotification(int subscription); + + /** + * Supply a pin to unlock the SIM for particular subscription. + * Blocks until a result is determined. + * @param pin The pin to check. + * @param subscription user preferred subscription. + * @return whether the operation was a success. + */ + boolean supplyPin(String pin, int subscription); + + /** + * Supply puk to unlock the SIM and set SIM pin to new pin. + * Blocks until a result is determined. + * @param puk The puk to check. + * pin The new pin to be set in SIM + * @param subscription user preferred subscription. + * @return whether the operation was a success. + */ + boolean supplyPuk(String puk, String pin, int subscription); + + /** + * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated + * without SEND (so dial is not appropriate) for + * a particular subscription. + * @param dialString the MMI command to be executed. + * @param subscription user preferred subscription. + * @return true if MMI command is executed. + */ + boolean handlePinMmi(String dialString, int subscription); + + /** + * Toggles the radio on or off on particular subscription. + * @param subscription user preferred subscription. + */ + void toggleRadioOnOff(int subscription); + + /** + * Set the radio to on or off on particular subscription. + * @param subscription user preferred subscription. + */ + boolean setRadio(boolean turnOn, int subscription); + + /** + * Request to update location information for a subscrition in service state + * @param subscription user preferred subscription. + */ + void updateServiceLocation(int subscription); + + /** + * Enable a specific APN type. + */ + int enableApnType(String type); + + /** + * Disable a specific APN type. + */ + int disableApnType(String type); + + /** + * Allow mobile data connections. + */ + boolean enableDataConnectivity(); + + /** + * Disallow mobile data connections. + */ + boolean disableDataConnectivity(); + + /** + * Report whether data connectivity is possible. + */ + boolean isDataConnectivityPossible(); + + /** + * Returns the call state for a subscription. + */ + int getCallState(int subscription); + int getDataActivity(); + int getDataState(); + + /** + * Returns the current active phone type as integer for particular subscription. + * Returns TelephonyManager.PHONE_TYPE_CDMA if RILConstants.CDMA_PHONE + * and TelephonyManager.PHONE_TYPE_GSM if RILConstants.GSM_PHONE + * @param subscription user preferred subscription. + */ + int getActivePhoneType(int subscription); + + + /** + * Returns the CDMA ERI icon index to display on particular subscription. + * @param subscription user preferred subscription. + */ + int getCdmaEriIconIndex(int subscription); + + /** + * Returns the CDMA ERI icon mode on particular subscription, + * 0 - ON + * 1 - FLASHING + * @param subscription user preferred subscription. + */ + int getCdmaEriIconMode(int subscription); + + /** + * Returns the CDMA ERI text for particular subscription, + * @param subscription user preferred subscription. + */ + String getCdmaEriText(int subscription); + + /** + * Returns true if OTA service provisioning needs to run. + * Only relevant on some technologies, others will always + * return false. + */ + boolean needsOtaServiceProvisioning(); + + /** + * Returns the unread count of voicemails for a subscription. + * @param subscription user preferred subscription. + * Returns the unread count of voicemails + */ + int getVoiceMessageCount(int subscription); + + /** + * Returns the network type of a subscription. + * @param subscription user preferred subscription. + * Returns the network type + */ + int getNetworkType(int subscription); + + /** + * Returns the data network type of a subscription + * @param subscription user preferred subscription. + * Returns the network type + */ + int getDataNetworkType(int subscription); + + /** + * Returns the voice network type of a subscription + * @param subscription user preferred subscription. + * Returns the network type + */ + int getVoiceNetworkType(int subscription); + + /** + * Return true if an ICC card is present for a subscription. + * @param subscription user preferred subscription. + * Return true if an ICC card is present + */ + boolean hasIccCard(int subscription); + + /** + * Return if the current radio is LTE on CDMA. This + * is a tri-state return value as for a period of time + * the mode may be unknown. + * + * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE} + * or {@link PHone#LTE_ON_CDMA_TRUE} + */ + int getLteOnCdmaMode(int subscription); + + /** + * Returns the all observed cell information of the device. + */ + List getAllCellInfo(); + + /** + * get default subscription + * @return subscription id + */ + int getDefaultSubscription(); + + /** + * get user prefered voice subscription + * @return subscription id + */ + int getPreferredVoiceSubscription(); + + /** + * get user prefered data subscription + * @return subscription id + */ + int getPreferredDataSubscription(); + + /* + * Set user prefered data subscription + * @return true if success + */ + boolean setPreferredDataSubscription(int subscription); +} + From c907d581b0c8be133f0c6487453f3aed1ce63531 Mon Sep 17 00:00:00 2001 From: Sankar Gonella Date: Fri, 31 May 2013 13:45:59 +0530 Subject: [PATCH 046/204] Ims: Fix the NullPointerException in getCountryIso() function Added Null check for detector.detectCountry(), if this function call fails, then CountryIso will be picked up based on the Locale. CRs-Fixed: 490472 Change-Id: Ia94891629cf6170a821f76a718d4b965ae7ab802 --- .../com/android/internal/telephony/CallerInfo.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java index 228a630e40d8f..4e9434682ffe6 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfo.java +++ b/telephony/java/com/android/internal/telephony/CallerInfo.java @@ -21,6 +21,7 @@ import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.location.CountryDetector; +import android.location.Country; import android.net.Uri; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.Data; @@ -566,14 +567,17 @@ private static String getGeoDescription(Context context, String number) { */ private static String getCurrentCountryIso(Context context, Locale locale) { String countryIso; + Country country; CountryDetector detector = (CountryDetector) context.getSystemService( Context.COUNTRY_DETECTOR); - if (detector != null) { - countryIso = detector.detectCountry().getCountryIso(); + if ((detector != null) && ((country = detector.detectCountry()) != null)) { + countryIso = country.getCountryIso(); + } else if (locale != null) { + countryIso = locale.getCountry(); + Rlog.w(TAG, "No CountryDetector; falling back to countryIso based on locale: " + + countryIso); } else { - countryIso = locale.getCountry(); - Rlog.w(TAG, "No CountryDetector; falling back to countryIso based on locale: " - + countryIso); + countryIso = "US"; //default value is "US" } return countryIso; } From c201757290b5fd15368457b1d39c4c4ca2eb5943 Mon Sep 17 00:00:00 2001 From: Jiju Kinattingal Date: Fri, 26 Oct 2012 12:57:02 +0530 Subject: [PATCH 047/204] Telephony(DSDS): MMS Auto Download. Add MMS_TRANSACTION property which enables silent or prompt modes to download MMS on non-DDS sub. Change-Id: I52fe5c095e0d69c2e0d4a7fd5bfeb77bf3289380 --- .../com/android/internal/telephony/TelephonyProperties.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index 0062b7edeb5a3..50d99b63b4010 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -228,4 +228,10 @@ public interface TelephonyProperties * Property to store default subscription. */ static final String PROPERTY_DEFAULT_SUBSCRIPTION = "persist.default.subscription"; + + /** + * Property to enable MMS Mode. + * Type: string ( default = silent, enable to = prompt ) + */ + static final String PROPERTY_MMS_TRANSACTION = "mms.transaction"; } From d35797804276f7625097e13466b44b253c9d6cbe Mon Sep 17 00:00:00 2001 From: Rakesh Pallerla Date: Mon, 8 Jul 2013 17:02:50 +0530 Subject: [PATCH 048/204] Telephony: Change Default subscription property name. Change default subscription property name from persist.default.subscription to persist.radio.default.sub so that it can be set by radio group access processes. Change-Id: I0a75eca8c88c54e8f68ebd029abecb17249a546a --- .../com/android/internal/telephony/TelephonyProperties.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 telephony/java/com/android/internal/telephony/TelephonyProperties.java diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java old mode 100644 new mode 100755 index 50d99b63b4010..793fc13b7eb86 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -227,7 +227,7 @@ public interface TelephonyProperties /** * Property to store default subscription. */ - static final String PROPERTY_DEFAULT_SUBSCRIPTION = "persist.default.subscription"; + static final String PROPERTY_DEFAULT_SUBSCRIPTION = "persist.radio.default.sub"; /** * Property to enable MMS Mode. From efc934f933d3bcda2fc6996bf56afdcd92885c56 Mon Sep 17 00:00:00 2001 From: Rakesh Pallerla Date: Thu, 1 Nov 2012 18:15:48 +0530 Subject: [PATCH 049/204] Telephony(MSIM): Add StatusBar support for MultiSim. Add support for Signal Strength icon display for MultiSim. Add support for NO SIM icon support for multiple SIMs. Change-Id: I11fb6ed37e7ba40b8db7840feedd109557128758 --- core/res/res/values/config.xml | 3 + .../res/layout/msim_signal_cluster_view.xml | 210 +++ .../SystemUI/res/layout/msim_status_bar.xml | 162 ++ .../res/layout/msim_super_status_bar.xml | 53 + .../res/layout/signal_cluster_view.xml | 7 + .../statusbar/MSimSignalClusterView.java | 246 ++++ .../systemui/statusbar/SignalClusterView.java | 18 +- .../statusbar/phone/PhoneStatusBar.java | 163 ++- .../statusbar/phone/PhoneStatusBarPolicy.java | 33 +- .../policy/MSimNetworkController.java | 1298 +++++++++++++++++ .../statusbar/policy/NetworkController.java | 134 +- .../statusbar/tablet/TabletStatusBar.java | 84 +- 12 files changed, 2296 insertions(+), 115 deletions(-) create mode 100644 packages/SystemUI/res/layout/msim_signal_cluster_view.xml create mode 100644 packages/SystemUI/res/layout/msim_status_bar.xml create mode 100644 packages/SystemUI/res/layout/msim_super_status_bar.xml create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/MSimSignalClusterView.java create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 24b6d269dc5aa..5588eb0d649e5 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2,6 +2,8 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/res/layout/msim_status_bar.xml b/packages/SystemUI/res/layout/msim_status_bar.xml new file mode 100644 index 0000000000000..937ace6d516e1 --- /dev/null +++ b/packages/SystemUI/res/layout/msim_status_bar.xml @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/res/layout/msim_super_status_bar.xml b/packages/SystemUI/res/layout/msim_super_status_bar.xml new file mode 100644 index 0000000000000..77234bb2d7d39 --- /dev/null +++ b/packages/SystemUI/res/layout/msim_super_status_bar.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml index 673d5a4db4e4e..8527ab6e31579 100644 --- a/packages/SystemUI/res/layout/signal_cluster_view.xml +++ b/packages/SystemUI/res/layout/signal_cluster_view.xml @@ -3,6 +3,8 @@ /* apps/common/assets/default/default/skins/StatusBar.xml ** ** Copyright 2011, The Android Open Source Project +** Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. +** Not a Contribution. ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -102,6 +104,11 @@ android:layout_width="wrap_content" android:layout_gravity="end|bottom" /> + mSimSignalClusters = new ArrayList(); + + public interface MSimSignalCluster { + void setWifiIndicators(boolean visible, int strengthIcon, int activityIcon, + String contentDescription); + void setMobileDataIndicators(boolean visible, int strengthIcon, int activityIcon, + int typeIcon, String contentDescription, String typeContentDescription, + int noSimIcon, int subscription); + void setIsAirplaneMode(boolean is, int airplaneIcon); + } + + /** + * Construct this controller object and register for updates. + */ + public MSimNetworkController(Context context) { + super(context); + + int numPhones = MSimTelephonyManager.getDefault().getPhoneCount(); + mMSimSignalStrength = new SignalStrength[numPhones]; + mMSimDataServiceState = new int[numPhones]; + mMSimServiceState = new ServiceState[numPhones]; + mMSimState = new IccCardConstants.State[numPhones]; + mMSimIconId = new int[numPhones]; + mMSimPhoneSignalIconId = new int[numPhones]; + mMSimDataTypeIconId = new int[numPhones]; + mNoMSimIconId = new int[numPhones]; + mMSimMobileActivityIconId = new int[numPhones]; + mMSimContentDescriptionPhoneSignal = new String[numPhones]; + mMSimLastPhoneSignalIconId = new int[numPhones]; + mMSimNetworkName = new String[numPhones]; + mMSimLastDataTypeIconId = new int[numPhones]; + mMSimDataConnected = new boolean[numPhones]; + mMSimDataSignalIconId = new int[numPhones]; + mMSimDataDirectionIconId = new int[numPhones]; + mMSimLastDataDirectionIconId = new int[numPhones]; + mMSimLastCombinedSignalIconId = new int[numPhones]; + mMSimcombinedSignalIconId = new int[numPhones]; + mMSimcombinedActivityIconId = new int[numPhones]; + mMSimDataActivity = new int[numPhones]; + mMSimContentDescriptionCombinedSignal = new String[numPhones]; + mMSimContentDescriptionDataType = new String[numPhones]; + mMSimLastSimIconId = new int[numPhones]; + + for (int i=0; i < numPhones; i++) { + mMSimSignalStrength[i] = new SignalStrength(); + mMSimServiceState[i] = new ServiceState(); + mMSimState[i] = IccCardConstants.State.READY; + // phone_signal + mMSimPhoneSignalIconId[i] = R.drawable.stat_sys_signal_null; + mMSimLastPhoneSignalIconId[i] = -1; + mMSimLastDataTypeIconId[i] = -1; + mMSimDataConnected[i] = false; + mMSimLastDataDirectionIconId[i] = -1; + mMSimLastCombinedSignalIconId[i] = -1; + mMSimcombinedSignalIconId[i] = 0; + mMSimcombinedActivityIconId[i] = 0; + mMSimDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE; + mMSimLastSimIconId[i] = 0; + mMSimNetworkName[i] = mNetworkNameDefault; + mMSimDataServiceState[i] = ServiceState.STATE_OUT_OF_SERVICE; + } + + mDefaultSubscription = MSimTelephonyManager.getDefault().getDefaultSubscription(); + mDataConnected = mMSimDataConnected[mDefaultSubscription]; + mSimState = mMSimState[mDefaultSubscription]; + mDataActivity = mMSimDataActivity[mDefaultSubscription]; + mDataServiceState = mMSimDataServiceState[mDefaultSubscription]; + mServiceState = mMSimServiceState[mDefaultSubscription]; + mSignalStrength = mMSimSignalStrength[mDefaultSubscription]; + mPhoneStateListener = mMSimPhoneStateListener[mDefaultSubscription]; + + mNetworkName = mMSimNetworkName[mDefaultSubscription]; + mPhoneSignalIconId = mMSimPhoneSignalIconId[mDefaultSubscription]; + mLastPhoneSignalIconId = mMSimLastPhoneSignalIconId[mDefaultSubscription]; + // data + data direction on phones + mDataDirectionIconId = mMSimDataDirectionIconId[mDefaultSubscription]; + mDataSignalIconId = mMSimDataSignalIconId[mDefaultSubscription]; + mDataTypeIconId = mMSimDataTypeIconId[mDefaultSubscription]; + mNoSimIconId = mNoMSimIconId[mDefaultSubscription]; + // overlay arrows for data direction + mMobileActivityIconId = mMSimMobileActivityIconId[mDefaultSubscription]; + + mContentDescriptionPhoneSignal = mMSimContentDescriptionPhoneSignal[mDefaultSubscription]; + mContentDescriptionCombinedSignal = mMSimContentDescriptionCombinedSignal[ + mDefaultSubscription]; + mContentDescriptionDataType = mMSimContentDescriptionDataType[mDefaultSubscription]; + + mLastDataDirectionIconId = mMSimLastDataDirectionIconId[mDefaultSubscription]; + mLastCombinedSignalIconId = mMSimLastCombinedSignalIconId[mDefaultSubscription]; + mLastDataTypeIconId = mMSimLastDataTypeIconId[mDefaultSubscription]; + mLastSimIconId = mMSimLastSimIconId[mDefaultSubscription]; + } + + @Override + protected void createWifiHandler() { + // wifi + mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + Handler handler = new MSimWifiHandler(); + mWifiChannel = new AsyncChannel(); + Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger(); + if (wifiMessenger != null) { + mWifiChannel.connect(mContext, handler, wifiMessenger); + } + } + + @Override + protected void registerPhoneStateListener(Context context) { + // telephony + int numPhones = MSimTelephonyManager.getDefault().getPhoneCount(); + mPhone = (MSimTelephonyManager)context.getSystemService(Context.MSIM_TELEPHONY_SERVICE); + mMSimPhoneStateListener = new PhoneStateListener[numPhones]; + for (int i=0; i < numPhones; i++) { + mMSimPhoneStateListener[i] = getPhoneStateListener(i); + mPhone.listen(mMSimPhoneStateListener[i], + PhoneStateListener.LISTEN_SERVICE_STATE + | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS + | PhoneStateListener.LISTEN_CALL_STATE + | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE + | PhoneStateListener.LISTEN_DATA_ACTIVITY); + } + } + + public void addSignalCluster(MSimSignalCluster cluster, int subscription) { + mSimSignalClusters.add(cluster); + refreshSignalCluster(cluster, subscription); + } + + public void refreshSignalCluster(MSimSignalCluster cluster, int subscription) { + cluster.setWifiIndicators( + // only show wifi in the cluster if connected or if wifi-only + mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature), + mWifiIconId, + mWifiActivityIconId, + mContentDescriptionWifi); + cluster.setMobileDataIndicators( + mHasMobileDataFeature, + mMSimPhoneSignalIconId[subscription], + mMSimMobileActivityIconId[subscription], + mMSimDataTypeIconId[subscription], + mMSimContentDescriptionPhoneSignal[subscription], + mMSimContentDescriptionDataType[subscription], + mNoMSimIconId[subscription], subscription); + if (mIsWimaxEnabled && mWimaxConnected) { + // wimax is special + cluster.setMobileDataIndicators( + true, + mAlwaysShowCdmaRssi ? mPhoneSignalIconId : mWimaxIconId, + mMSimMobileActivityIconId[subscription], + mMSimDataTypeIconId[subscription], + mContentDescriptionWimax, + mMSimContentDescriptionDataType[subscription], + mNoMSimIconId[subscription], subscription); + } else { + // normal mobile data + cluster.setMobileDataIndicators( + mHasMobileDataFeature, + mShowPhoneRSSIForData ? mMSimPhoneSignalIconId[subscription] + : mMSimDataSignalIconId[subscription], + mMSimMobileActivityIconId[subscription], + mMSimDataTypeIconId[subscription], + mMSimContentDescriptionPhoneSignal[subscription], + mMSimContentDescriptionDataType[subscription], + mNoMSimIconId[subscription], subscription); + } + cluster.setIsAirplaneMode(mAirplaneMode, mAirplaneIconId); + } + + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (action.equals(WifiManager.RSSI_CHANGED_ACTION) + || action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION) + || action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { + updateWifiState(intent); + refreshViews(mDefaultSubscription); + } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) { + updateSimState(intent); + for (int sub = 0; sub < MSimTelephonyManager.getDefault().getPhoneCount(); sub++) { + updateDataIcon(sub); + refreshViews(sub); + } + } else if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) { + final int subscription = intent.getIntExtra(MSimConstants.SUBSCRIPTION_KEY, 0); + Slog.d(TAG, "Received SPN update on sub :" + subscription); + updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false), + intent.getStringExtra(TelephonyIntents.EXTRA_SPN), + intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false), + intent.getStringExtra(TelephonyIntents.EXTRA_PLMN), subscription); + refreshViews(subscription); + } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) || + action.equals(ConnectivityManager.INET_CONDITION_ACTION)) { + updateConnectivity(intent); + refreshViews(mDefaultSubscription); + } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { + refreshViews(mDefaultSubscription); + } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { + updateAirplaneMode(); + for (int i = 0; i < MSimTelephonyManager.getDefault().getPhoneCount(); i++) { + updateSimIcon(i); + } + refreshViews(mDefaultSubscription); + } else if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION) || + action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION) || + action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) { + updateWimaxState(intent); + refreshViews(mDefaultSubscription); + } + } + + // ===== Telephony ============================================================== + + private PhoneStateListener getPhoneStateListener(int subscription) { + PhoneStateListener mMSimPhoneStateListener = new PhoneStateListener(subscription) { + @Override + public void onSignalStrengthsChanged(SignalStrength signalStrength) { + if (DEBUG) { + Slog.d(TAG, "onSignalStrengthsChanged received on subscription :" + + mSubscription + "signalStrength=" + signalStrength + + ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel()))); + } + mMSimSignalStrength[mSubscription] = signalStrength; + updateTelephonySignalStrength(mSubscription); + refreshViews(mSubscription); + } + + @Override + public void onServiceStateChanged(ServiceState state) { + if (DEBUG) { + Slog.d(TAG, "onServiceStateChanged received on subscription :" + + mSubscription + "state=" + state.getState()); + } + mMSimServiceState[mSubscription] = state; + updateTelephonySignalStrength(mSubscription); + updateDataNetType(mSubscription); + updateDataIcon(mSubscription); + refreshViews(mSubscription); + } + + @Override + public void onCallStateChanged(int state, String incomingNumber) { + if (DEBUG) { + Slog.d(TAG, "onCallStateChanged received on subscription :" + + mSubscription + "state=" + state); + } + // In cdma, if a voice call is made, RSSI should switch to 1x. + if (isCdma(mSubscription)) { + updateTelephonySignalStrength(mSubscription); + refreshViews(mSubscription); + } + } + + @Override + public void onDataConnectionStateChanged(int state, int networkType) { + if (DEBUG) { + Slog.d(TAG, "onDataConnectionStateChanged received on subscription :" + + mSubscription + "state=" + state + " type=" + networkType); + } + + // DSDS case: Data is active only on DDS. Ignore the Data Connection + // State changed notifications of the other NON-DDS. + if (mSubscription == + MSimTelephonyManager.getDefault().getPreferredDataSubscription()) { + mDataState = state; + mDataNetType = networkType; + } + updateDataNetType(mSubscription); + updateDataIcon(mSubscription); + refreshViews(mSubscription); + } + + @Override + public void onDataActivity(int direction) { + if (DEBUG) { + Slog.d(TAG, "onDataActivity received on subscription :" + + mSubscription + "direction=" + direction); + } + mMSimDataActivity[mSubscription] = direction; + updateDataIcon(mSubscription); + refreshViews(mSubscription); + } + }; + return mMSimPhoneStateListener; + } + + // ===== Wifi =================================================================== + + class MSimWifiHandler extends WifiHandler { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case WifiManager.DATA_ACTIVITY_NOTIFICATION: + if (msg.arg1 != mWifiActivity) { + mWifiActivity = msg.arg1; + refreshViews(MSimTelephonyManager.getDefault(). + getPreferredDataSubscription()); + } + break; + default: + super.handleMessage(msg); + break; + } + } + } + + @Override + protected void updateSimState(Intent intent) { + IccCardConstants.State simState; + String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); + // Obtain the subscription info from intent. + int sub = intent.getIntExtra(MSimConstants.SUBSCRIPTION_KEY, 0); + Slog.d(TAG, "updateSimState for subscription :" + sub); + if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { + simState = IccCardConstants.State.ABSENT; + } + else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) { + simState = IccCardConstants.State.READY; + } + else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) { + final String lockedReason = intent.getStringExtra(IccCardConstants. + INTENT_KEY_LOCKED_REASON); + if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) { + simState = IccCardConstants.State.PIN_REQUIRED; + } + else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { + simState = IccCardConstants.State.PUK_REQUIRED; + } + else { + simState = IccCardConstants.State.NETWORK_LOCKED; + } + } else { + simState = IccCardConstants.State.UNKNOWN; + } + mMSimState[sub] = simState; + Slog.d(TAG, "updateSimState simState =" + mMSimState[sub]); + updateSimIcon(sub); + updateDataIcon(sub); + } + + private boolean isCdma(int subscription) { + return (mMSimSignalStrength[subscription] != null) && + !mMSimSignalStrength[subscription].isGsm(); + } + + private boolean hasService(int subscription) { + ServiceState ss = mMSimServiceState[subscription]; + if (ss != null) { + switch (ss.getState()) { + case ServiceState.STATE_OUT_OF_SERVICE: + case ServiceState.STATE_POWER_OFF: + return false; + default: + return true; + } + } else { + return false; + } + } + + private final void updateTelephonySignalStrength(int subscription) { + Slog.d(TAG, "updateTelephonySignalStrength: subscription =" + subscription); + if (!hasService(subscription) && + (mMSimDataServiceState[subscription] != ServiceState.STATE_IN_SERVICE)) { + if (DEBUG) Slog.d(TAG, " No service"); + mMSimPhoneSignalIconId[subscription] = R.drawable.stat_sys_signal_null; + mMSimDataSignalIconId[subscription] = R.drawable.stat_sys_signal_null; + } else { + if (mMSimSignalStrength[subscription] == null || (mMSimServiceState == null)) { + if (DEBUG) { + Slog.d(TAG, " Null object, mMSimSignalStrength= " + + mMSimSignalStrength[subscription] + + " mMSimServiceState " + mMSimServiceState[subscription]); + } + mMSimPhoneSignalIconId[subscription] = R.drawable.stat_sys_signal_null; + mMSimDataSignalIconId[subscription] = R.drawable.stat_sys_signal_null; + mMSimContentDescriptionPhoneSignal[subscription] = mContext.getString( + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]); + } else { + int iconLevel; + int[] iconList; + if (isCdma(subscription) && mAlwaysShowCdmaRssi) { + mLastSignalLevel = iconLevel = mMSimSignalStrength[subscription].getCdmaLevel(); + if(DEBUG) Slog.d(TAG, "mAlwaysShowCdmaRssi= " + mAlwaysShowCdmaRssi + + " set to cdmaLevel= " + + mMSimSignalStrength[subscription].getCdmaLevel() + + " instead of level= " + mMSimSignalStrength[subscription].getLevel()); + } else { + mLastSignalLevel = iconLevel = mMSimSignalStrength[subscription].getLevel(); + } + + // Though mPhone is a Manager, this call is not an IPC + if ((isCdma(subscription) && isCdmaEri(subscription)) || + mPhone.isNetworkRoaming(subscription)) { + iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition]; + } else { + iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition]; + } + + Slog.d(TAG, "updateTelephonySignalStrength iconList = " + iconList + "iconLevel = " + + iconLevel + " mInetCondition = " + mInetCondition); + mMSimPhoneSignalIconId[subscription] = iconList[iconLevel]; + mMSimContentDescriptionPhoneSignal[subscription] = mContext.getString( + AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[iconLevel]); + + mMSimDataSignalIconId[subscription] = TelephonyIcons + .DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel]; + } + } + } + + private final void updateDataNetType(int subscription) { + // DSDS case: Data is active only on DDS. Clear the icon for NON-DDS + int dataSub = MSimTelephonyManager.getDefault().getPreferredDataSubscription(); + if (subscription != dataSub) { + Slog.d(TAG,"updateDataNetType: SUB" + subscription + + " is not DDS(=SUB" + dataSub + ")!"); + mMSimDataTypeIconId[subscription] = 0; + } else { + if (mIsWimaxEnabled && mWimaxConnected) { + // wimax is a special 4g network not handled by telephony + mDataIconList = TelephonyIcons.DATA_4G[mInetCondition]; + mMSimDataTypeIconId[subscription] = R.drawable.stat_sys_data_connected_4g; + mMSimContentDescriptionDataType[subscription] = mContext.getString( + R.string.accessibility_data_connection_4g); + } else { + Slog.d(TAG,"updateDataNetType sub = " + subscription + + " mDataNetType = " + mDataNetType); + switch (mDataNetType) { + case TelephonyManager.NETWORK_TYPE_UNKNOWN: + if (DEBUG) { + Slog.e(TAG, "updateDataNetType NETWORK_TYPE_UNKNOWN"); + } + if (!mShowAtLeastThreeGees) { + mDataIconList = TelephonyIcons.DATA_G[mInetCondition]; + mMSimDataTypeIconId[subscription] = 0; + mMSimContentDescriptionDataType[subscription] = mContext.getString( + R.string.accessibility_data_connection_gprs); + break; + } else { + // fall through + } + case TelephonyManager.NETWORK_TYPE_EDGE: + if (!mShowAtLeastThreeGees) { + mDataIconList = TelephonyIcons.DATA_E[mInetCondition]; + mMSimDataTypeIconId[subscription] = R.drawable.stat_sys_data_connected_e; + mMSimContentDescriptionDataType[subscription] = mContext.getString( + R.string.accessibility_data_connection_edge); + break; + } else { + // fall through + } + case TelephonyManager.NETWORK_TYPE_UMTS: + mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; + mMSimDataTypeIconId[subscription] = R.drawable.stat_sys_data_connected_3g; + mMSimContentDescriptionDataType[subscription] = mContext.getString( + R.string.accessibility_data_connection_3g); + break; + case TelephonyManager.NETWORK_TYPE_HSDPA: + case TelephonyManager.NETWORK_TYPE_HSUPA: + case TelephonyManager.NETWORK_TYPE_HSPA: + case TelephonyManager.NETWORK_TYPE_HSPAP: + if (mHspaDataDistinguishable) { + mDataIconList = TelephonyIcons.DATA_H[mInetCondition]; + mMSimDataTypeIconId[subscription] = R.drawable. + stat_sys_data_connected_h; + mMSimContentDescriptionDataType[subscription] = mContext.getString( + R.string.accessibility_data_connection_3_5g); + } else { + mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; + mMSimDataTypeIconId[subscription] = R.drawable. + stat_sys_data_connected_3g; + mMSimContentDescriptionDataType[subscription] = mContext.getString( + R.string.accessibility_data_connection_3g); + } + break; + case TelephonyManager.NETWORK_TYPE_CDMA: + // display 1xRTT for IS95A/B + mDataIconList = TelephonyIcons.DATA_1X[mInetCondition]; + mMSimDataTypeIconId[subscription] = R.drawable.stat_sys_data_connected_1x; + mMSimContentDescriptionDataType[subscription] = mContext.getString( + R.string.accessibility_data_connection_cdma); + break; + case TelephonyManager.NETWORK_TYPE_1xRTT: + mDataIconList = TelephonyIcons.DATA_1X[mInetCondition]; + mMSimDataTypeIconId[subscription] = R.drawable.stat_sys_data_connected_1x; + mMSimContentDescriptionDataType[subscription] = mContext.getString( + R.string.accessibility_data_connection_cdma); + break; + case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through + case TelephonyManager.NETWORK_TYPE_EVDO_A: + case TelephonyManager.NETWORK_TYPE_EVDO_B: + case TelephonyManager.NETWORK_TYPE_EHRPD: + mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; + mMSimDataTypeIconId[subscription] = R.drawable.stat_sys_data_connected_3g; + mMSimContentDescriptionDataType[subscription] = mContext.getString( + R.string.accessibility_data_connection_3g); + break; + case TelephonyManager.NETWORK_TYPE_LTE: + mDataIconList = TelephonyIcons.DATA_4G[mInetCondition]; + mMSimDataTypeIconId[subscription] = R.drawable.stat_sys_data_connected_4g; + mMSimContentDescriptionDataType[subscription] = mContext.getString( + R.string.accessibility_data_connection_4g); + break; + case TelephonyManager.NETWORK_TYPE_GPRS: + if (!mShowAtLeastThreeGees) { + mDataIconList = TelephonyIcons.DATA_G[mInetCondition]; + mMSimDataTypeIconId[subscription] = R.drawable.stat_sys_data_connected_g; + mMSimContentDescriptionDataType[subscription] = mContext.getString( + R.string.accessibility_data_connection_gprs); + } else { + mDataIconList = TelephonyIcons.DATA_3G[mInetCondition]; + mMSimDataTypeIconId[subscription] = + R.drawable.stat_sys_data_connected_3g; + mMSimContentDescriptionDataType[subscription] = mContext.getString( + R.string.accessibility_data_connection_3g); + } + break; + default: + if (DEBUG) { + Slog.e(TAG, "updateDataNetType unknown radio:" + mDataNetType); + } + mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + mMSimDataTypeIconId[subscription] = 0; + break; + } + } + } + + if (isCdma(subscription)) { + if (isCdmaEri(subscription)) { + mMSimDataTypeIconId[subscription] = R.drawable.stat_sys_data_connected_roam; + } + } else if (mPhone.isNetworkRoaming(subscription)) { + mMSimDataTypeIconId[subscription] = R.drawable.stat_sys_data_connected_roam; + } + } + + boolean isCdmaEri(int subscription) { + if ((mMSimServiceState[subscription] != null) + && (hasService(subscription) || (mMSimDataServiceState[subscription] + == ServiceState.STATE_IN_SERVICE))) { + final int iconIndex = mMSimServiceState[subscription].getCdmaEriIconIndex(); + if (iconIndex != EriInfo.ROAMING_INDICATOR_OFF) { + final int iconMode = mMSimServiceState[subscription].getCdmaEriIconMode(); + if (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL + || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH) { + return true; + } + } + } + return false; + } + + private final void updateSimIcon(int cardIndex) { + Slog.d(TAG,"In updateSimIcon card =" + cardIndex + ", simState= " + mMSimState[cardIndex]); + if (mMSimState[cardIndex] == IccCardConstants.State.ABSENT) { + mNoMSimIconId[cardIndex] = R.drawable.stat_sys_no_sim; + } else { + mNoMSimIconId[cardIndex] = 0; + } + refreshViews(cardIndex); + } + + private final void updateDataIcon(int subscription) { + Slog.d(TAG,"updateDataIcon subscription =" + subscription); + int iconId = 0; + boolean visible = true; + + int dataSub = MSimTelephonyManager.getDefault().getPreferredDataSubscription(); + Slog.d(TAG,"updateDataIcon dataSub =" + dataSub); + // DSDS case: Data is active only on DDS. Clear the icon for NON-DDS + if (subscription != dataSub) { + mMSimDataConnected[subscription] = false; + Slog.d(TAG,"updateDataIconi: SUB" + subscription + + " is not DDS. Clear the mMSimDataConnected Flag and return"); + return; + } + + Slog.d(TAG,"updateDataIcon when SimState =" + mMSimState[subscription]); + if (mDataNetType == TelephonyManager.NETWORK_TYPE_UNKNOWN) { + // If data network type is unknown do not display data icon + visible = false; + } else if (!isCdma(subscription)) { + Slog.d(TAG,"updateDataIcon when gsm mMSimState =" + mMSimState[subscription]); + // GSM case, we have to check also the sim state + if (mMSimState[subscription] == IccCardConstants.State.READY || + mMSimState[subscription] == IccCardConstants.State.UNKNOWN) { + if (mDataState == TelephonyManager.DATA_CONNECTED) { + switch (mMSimDataActivity[subscription]) { + case TelephonyManager.DATA_ACTIVITY_IN: + iconId = mDataIconList[1]; + break; + case TelephonyManager.DATA_ACTIVITY_OUT: + iconId = mDataIconList[2]; + break; + case TelephonyManager.DATA_ACTIVITY_INOUT: + iconId = mDataIconList[3]; + break; + default: + iconId = mDataIconList[0]; + break; + } + mMSimDataDirectionIconId[subscription] = iconId; + } else { + iconId = 0; + visible = false; + } + } else { + Slog.d(TAG,"updateDataIcon when no sim"); + iconId = R.drawable.stat_sys_no_sim; + visible = false; // no SIM? no data + } + } else { + // CDMA case, mMSimDataActivity can be also DATA_ACTIVITY_DORMANT + if (mDataState == TelephonyManager.DATA_CONNECTED) { + switch (mMSimDataActivity[subscription]) { + case TelephonyManager.DATA_ACTIVITY_IN: + iconId = mDataIconList[1]; + break; + case TelephonyManager.DATA_ACTIVITY_OUT: + iconId = mDataIconList[2]; + break; + case TelephonyManager.DATA_ACTIVITY_INOUT: + iconId = mDataIconList[3]; + break; + case TelephonyManager.DATA_ACTIVITY_DORMANT: + default: + iconId = mDataIconList[0]; + break; + } + } else { + iconId = 0; + visible = false; + } + } + + // yuck - this should NOT be done by the status bar + long ident = Binder.clearCallingIdentity(); + try { + mBatteryStats.notePhoneDataConnectionState(mPhone. + getNetworkType(subscription), visible); + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } + + mMSimDataDirectionIconId[subscription] = iconId; + mMSimDataConnected[subscription] = visible; + Slog.d(TAG,"updateDataIcon when mMSimDataConnected =" + mMSimDataConnected[subscription]); + } + + void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn, + int subscription) { + if (false) { + Slog.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn + + " showPlmn=" + showPlmn + " plmn=" + plmn); + } + StringBuilder str = new StringBuilder(); + boolean something = false; + if (showPlmn && plmn != null) { + str.append(plmn); + something = true; + } + if (showSpn && spn != null) { + if (something) { + str.append(mNetworkNameSeparator); + } + str.append(spn); + something = true; + } + if (something) { + mMSimNetworkName[subscription] = str.toString(); + } else { + mMSimNetworkName[subscription] = mNetworkNameDefault; + } + } + + // ===== Full or limited Internet connectivity ================================== + @Override + protected void updateConnectivity(Intent intent) { + if (CHATTY) { + Slog.d(TAG, "updateConnectivity: intent=" + intent); + } + + final ConnectivityManager connManager = (ConnectivityManager) mContext + .getSystemService(Context.CONNECTIVITY_SERVICE); + final NetworkInfo info = connManager.getActiveNetworkInfo(); + + // Are we connected at all, by any interface? + mConnected = info != null && info.isConnected(); + if (mConnected) { + mConnectedNetworkType = info.getType(); + mConnectedNetworkTypeName = info.getTypeName(); + } else { + mConnectedNetworkType = ConnectivityManager.TYPE_NONE; + mConnectedNetworkTypeName = null; + } + + int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0); + + if (CHATTY) { + Slog.d(TAG, "updateConnectivity: networkInfo=" + info); + Slog.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus); + } + + mInetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0); + if (info != null && info.getType() == ConnectivityManager.TYPE_BLUETOOTH) { + mBluetoothTethered = info.isConnected(); + } else { + mBluetoothTethered = false; + } + + // We want to update all the icons, all at once, for any condition change + updateWimaxIcons(); + for (int sub = 0; sub < MSimTelephonyManager.getDefault().getPhoneCount(); sub++) { + updateDataNetType(sub); + updateDataIcon(sub); + updateTelephonySignalStrength(sub); + } + updateWifiIcons(); + } + + // ===== Update the views ======================================================= + + protected void refreshViews(int subscription) { + Context context = mContext; + + String combinedLabel = ""; + String mobileLabel = ""; + String wifiLabel = ""; + int N; + Slog.d(TAG,"refreshViews subscription =" + subscription + "mMSimDataConnected =" + + mMSimDataConnected[subscription]); + Slog.d(TAG,"refreshViews mMSimDataActivity =" + mMSimDataActivity[subscription]); + if (!mHasMobileDataFeature) { + mMSimDataSignalIconId[subscription] = mMSimPhoneSignalIconId[subscription] = 0; + mobileLabel = ""; + } else { + // We want to show the carrier name if in service and either: + // - We are connected to mobile data, or + // - We are not connected to mobile data, as long as the *reason* packets are not + // being routed over that link is that we have better connectivity via wifi. + // If data is disconnected for some other reason but wifi (or ethernet/bluetooth) + // is connected, we show nothing. + // Otherwise (nothing connected) we show "No internet connection". + + if (mMSimDataConnected[subscription]) { + mobileLabel = mMSimNetworkName[subscription]; + } else if (mConnected) { + if (hasService(subscription)) { + mobileLabel = mMSimNetworkName[subscription]; + } else { + mobileLabel = ""; + } + } else { + mobileLabel + = context.getString(R.string.status_bar_settings_signal_meter_disconnected); + } + + // Now for things that should only be shown when actually using mobile data. + if (mMSimDataConnected[subscription]) { + mMSimcombinedSignalIconId[subscription] = mMSimDataSignalIconId[subscription]; + switch (mMSimDataActivity[subscription]) { + case TelephonyManager.DATA_ACTIVITY_IN: + mMSimMobileActivityIconId[subscription] = R.drawable.stat_sys_signal_in; + break; + case TelephonyManager.DATA_ACTIVITY_OUT: + mMSimMobileActivityIconId[subscription] = R.drawable.stat_sys_signal_out; + break; + case TelephonyManager.DATA_ACTIVITY_INOUT: + mMSimMobileActivityIconId[subscription] = R.drawable.stat_sys_signal_inout; + break; + default: + mMSimMobileActivityIconId[subscription] = 0; + break; + } + + combinedLabel = mobileLabel; + mMSimcombinedActivityIconId[subscription] = mMSimMobileActivityIconId[subscription]; + // set by updateDataIcon() + mMSimcombinedSignalIconId[subscription] = mMSimDataSignalIconId[subscription]; + mMSimContentDescriptionCombinedSignal[subscription] = + mMSimContentDescriptionDataType[subscription]; + } + } + + if (mWifiConnected) { + if (mWifiSsid == null) { + wifiLabel = context.getString( + R.string.status_bar_settings_signal_meter_wifi_nossid); + mWifiActivityIconId = 0; // no wifis, no bits + } else { + wifiLabel = mWifiSsid; + if (DEBUG) { + wifiLabel += "xxxxXXXXxxxxXXXX"; + } + switch (mWifiActivity) { + case WifiManager.DATA_ACTIVITY_IN: + mWifiActivityIconId = R.drawable.stat_sys_wifi_in; + break; + case WifiManager.DATA_ACTIVITY_OUT: + mWifiActivityIconId = R.drawable.stat_sys_wifi_out; + break; + case WifiManager.DATA_ACTIVITY_INOUT: + mWifiActivityIconId = R.drawable.stat_sys_wifi_inout; + break; + case WifiManager.DATA_ACTIVITY_NONE: + mWifiActivityIconId = 0; + break; + } + } + + mMSimcombinedActivityIconId[subscription] = mWifiActivityIconId; + combinedLabel = wifiLabel; + mMSimcombinedSignalIconId[subscription] = mWifiIconId; // set by updateWifiIcons() + mMSimContentDescriptionCombinedSignal[subscription] = mContentDescriptionWifi; + } else { + if (mHasMobileDataFeature) { + wifiLabel = ""; + } else { + wifiLabel = context.getString( + R.string.status_bar_settings_signal_meter_disconnected); + } + } + + if (mBluetoothTethered) { + combinedLabel = mContext.getString(R.string.bluetooth_tethered); + mMSimcombinedSignalIconId[subscription] = mBluetoothTetherIconId; + mMSimContentDescriptionCombinedSignal[subscription] = mContext.getString( + R.string.accessibility_bluetooth_tether); + } + + final boolean ethernetConnected = (mConnectedNetworkType == + ConnectivityManager.TYPE_ETHERNET); + if (ethernetConnected) { + // TODO: icons and strings for Ethernet connectivity + combinedLabel = mConnectedNetworkTypeName; + } + + if (mAirplaneMode && + (mMSimServiceState[subscription] == null || (!hasService(subscription) + && !mMSimServiceState[subscription].isEmergencyOnly()))) { + // Only display the flight-mode icon if not in "emergency calls only" mode. + + // look again; your radios are now airplanes + mMSimContentDescriptionPhoneSignal[subscription] = mContext.getString( + R.string.accessibility_airplane_mode); + mAirplaneIconId = R.drawable.stat_sys_signal_flightmode; + mMSimPhoneSignalIconId[subscription] = mMSimDataSignalIconId[subscription] + = mMSimDataTypeIconId[subscription] = 0; + mNoMSimIconId[subscription] = 0; + + // combined values from connected wifi take precedence over airplane mode + if (mWifiConnected) { + // Suppress "No internet connection." from mobile if wifi connected. + mobileLabel = ""; + } else { + if (mHasMobileDataFeature) { + // let the mobile icon show "No internet connection." + wifiLabel = ""; + } else { + wifiLabel = context.getString( + R.string.status_bar_settings_signal_meter_disconnected); + combinedLabel = wifiLabel; + } + mMSimContentDescriptionCombinedSignal[subscription] = + mContentDescriptionPhoneSignal; + mMSimcombinedSignalIconId[subscription] = mMSimDataSignalIconId[subscription]; + } + mMSimDataTypeIconId[subscription] = 0; + mNoMSimIconId[subscription] = 0; + + mMSimcombinedSignalIconId[subscription] = mMSimDataSignalIconId[subscription]; + } + else if (!mMSimDataConnected[subscription] && !mWifiConnected && !mBluetoothTethered && + !mWimaxConnected && !ethernetConnected) { + // pretty much totally disconnected + + combinedLabel = context.getString( + R.string.status_bar_settings_signal_meter_disconnected); + // On devices without mobile radios, we want to show the wifi icon + mMSimcombinedSignalIconId[subscription] = + mHasMobileDataFeature ? mMSimDataSignalIconId[subscription] : mWifiIconId; + mMSimContentDescriptionCombinedSignal[subscription] = mHasMobileDataFeature + ? mMSimContentDescriptionDataType[subscription] : mContentDescriptionWifi; + + mMSimDataTypeIconId[subscription] = 0; + if (isCdma(subscription)) { + if (isCdmaEri(subscription)) { + mMSimDataTypeIconId[subscription] = R.drawable.stat_sys_data_connected_roam; + } + } else if (mPhone.isNetworkRoaming(subscription)) { + mMSimDataTypeIconId[subscription] = R.drawable.stat_sys_data_connected_roam; + } + } + if (DEBUG) { + Slog.d(TAG, "refreshViews connected={" + + (mWifiConnected?" wifi":"") + + (mMSimDataConnected[subscription]?" data":"") + + " } level=" + + ((mMSimSignalStrength[subscription] == null)?"??":Integer.toString + (mMSimSignalStrength[subscription].getLevel())) + + " mMSimcombinedSignalIconId=0x" + + Integer.toHexString(mMSimcombinedSignalIconId[subscription]) + + "/" + getResourceName(mMSimcombinedSignalIconId[subscription]) + + " mMSimcombinedActivityIconId=0x" + Integer.toHexString + (mMSimcombinedActivityIconId[subscription]) + + " mAirplaneMode=" + mAirplaneMode + + " mMSimDataActivity=" + mMSimDataActivity[subscription] + + " mMSimPhoneSignalIconId=0x" + Integer.toHexString + (mMSimPhoneSignalIconId[subscription]) + + " mMSimDataDirectionIconId=0x" + Integer.toHexString + (mMSimDataDirectionIconId[subscription]) + + " mMSimDataSignalIconId=0x" + Integer.toHexString + (mMSimDataSignalIconId[subscription]) + + " mMSimDataTypeIconId=0x" + Integer.toHexString + (mMSimDataTypeIconId[subscription]) + + " mNoMSimIconId=0x" + Integer.toHexString(mNoMSimIconId[subscription]) + + " mWifiIconId=0x" + Integer.toHexString(mWifiIconId) + + " mBluetoothTetherIconId=0x" + Integer.toHexString(mBluetoothTetherIconId)); + } + + if (mMSimLastPhoneSignalIconId[subscription] != mMSimPhoneSignalIconId[subscription] + || mLastDataDirectionOverlayIconId != mMSimcombinedActivityIconId[subscription] + || mLastWifiIconId != mWifiIconId + || mLastWimaxIconId != mWimaxIconId + || mMSimLastDataTypeIconId[subscription] != mMSimDataTypeIconId[subscription] + || mLastAirplaneMode != mAirplaneMode + || mMSimLastSimIconId[subscription] != mNoMSimIconId[subscription]) + { + // NB: the mLast*s will be updated later + for (MSimSignalCluster cluster : mSimSignalClusters) { + refreshSignalCluster(cluster, subscription); + } + } + + if (mLastAirplaneMode != mAirplaneMode) { + mLastAirplaneMode = mAirplaneMode; + } + + // the phone icon on phones + if (mMSimLastPhoneSignalIconId[subscription] != mMSimPhoneSignalIconId[subscription]) { + mMSimLastPhoneSignalIconId[subscription] = mMSimPhoneSignalIconId[subscription]; + N = mPhoneSignalIconViews.size(); + for (int i=0; i mPhoneSignalIconViews = new ArrayList(); ArrayList mDataDirectionIconViews = new ArrayList(); ArrayList mDataDirectionOverlayIconViews = new ArrayList(); @@ -168,7 +174,7 @@ public class NetworkController extends BroadcastReceiver { int mLastDataTypeIconId = -1; String mLastCombinedLabel = ""; - private boolean mHasMobileDataFeature; + protected boolean mHasMobileDataFeature; boolean mDataAndWifiStacked = false; @@ -179,7 +185,8 @@ public interface SignalCluster { void setWifiIndicators(boolean visible, int strengthIcon, int activityIcon, String contentDescription); void setMobileDataIndicators(boolean visible, int strengthIcon, int activityIcon, - int typeIcon, String contentDescription, String typeContentDescription); + int typeIcon, String contentDescription, String typeContentDescription, + int noSimIcon); void setIsAirplaneMode(boolean is, int airplaneIcon); void setEtherIndicators(boolean visible, int etherIcon, String contentDescription); } @@ -214,13 +221,7 @@ public NetworkController(Context context) { updateWimaxIcons(); // telephony - mPhone = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); - mPhone.listen(mPhoneStateListener, - PhoneStateListener.LISTEN_SERVICE_STATE - | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS - | PhoneStateListener.LISTEN_CALL_STATE - | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE - | PhoneStateListener.LISTEN_DATA_ACTIVITY); + registerPhoneStateListener(context); mHspaDataDistinguishable = mContext.getResources().getBoolean( R.bool.config_hspa_data_distinguishable); mNetworkNameSeparator = mContext.getString(R.string.status_bar_network_name_separator); @@ -228,14 +229,7 @@ public NetworkController(Context context) { com.android.internal.R.string.lockscreen_carrier_default); mNetworkName = mNetworkNameDefault; - // wifi - mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); - Handler handler = new WifiHandler(); - mWifiChannel = new AsyncChannel(); - Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger(); - if (wifiMessenger != null) { - mWifiChannel.connect(mContext, handler, wifiMessenger); - } + createWifiHandler(); // broadcasts IntentFilter filter = new IntentFilter(); @@ -278,6 +272,28 @@ public boolean isEmergencyOnly() { return (mServiceState != null && mServiceState.isEmergencyOnly()); } + protected void createWifiHandler() { + // wifi + mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + Handler handler = new WifiHandler(); + mWifiChannel = new AsyncChannel(); + Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger(); + if (wifiMessenger != null) { + mWifiChannel.connect(mContext, handler, wifiMessenger); + } + } + + protected void registerPhoneStateListener(Context context) { + // telephony + mPhone = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); + mPhone.listen(mPhoneStateListener, + PhoneStateListener.LISTEN_SERVICE_STATE + | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS + | PhoneStateListener.LISTEN_CALL_STATE + | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE + | PhoneStateListener.LISTEN_DATA_ACTIVITY); + } + public void addPhoneSignalIconView(ImageView v) { mPhoneSignalIconViews.add(v); } @@ -357,7 +373,8 @@ public void refreshSignalCluster(SignalCluster cluster) { mMobileActivityIconId, mDataTypeIconId, mContentDescriptionWimax, - mContentDescriptionDataType); + mContentDescriptionDataType, + mNoSimIconId); } else { // normal mobile data cluster.setMobileDataIndicators( @@ -366,7 +383,8 @@ public void refreshSignalCluster(SignalCluster cluster) { mMobileActivityIconId, mDataTypeIconId, mContentDescriptionPhoneSignal, - mContentDescriptionDataType); + mContentDescriptionDataType, + mNoSimIconId); } cluster.setIsAirplaneMode(mAirplaneMode, mAirplaneIconId); } @@ -430,6 +448,7 @@ public void onReceive(Context context, Intent intent) { } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { refreshLocale(); updateAirplaneMode(); + updateSimIcon(); refreshViews(); } else if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION) || action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION) || @@ -502,7 +521,7 @@ public void onDataActivity(int direction) { } }; - private final void updateSimState(Intent intent) { + protected void updateSimState(Intent intent) { String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { mSimState = IccCardConstants.State.ABSENT; @@ -528,6 +547,7 @@ else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { } else { mSimState = IccCardConstants.State.UNKNOWN; } + updateSimIcon(); } private boolean isCdma() { @@ -548,7 +568,7 @@ private boolean hasService() { } } - private void updateAirplaneMode() { + protected void updateAirplaneMode() { mAirplaneMode = (Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0) == 1); } @@ -768,6 +788,16 @@ boolean isCdmaEri() { return false; } + private final void updateSimIcon() { + Slog.d(TAG,"In updateSimIcon simState= " + mSimState); + if (mSimState == IccCardConstants.State.ABSENT) { + mNoSimIconId = R.drawable.stat_sys_no_sim; + } else { + mNoSimIconId = 0; + } + refreshViews(); + } + private final void updateDataIcon() { int iconId; boolean visible = true; @@ -889,7 +919,7 @@ public void handleMessage(Message msg) { } } - private void updateWifiState(Intent intent) { + protected void updateWifiState(Intent intent) { final String action = intent.getAction(); if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { mWifiEnabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, @@ -924,7 +954,7 @@ private void updateWifiState(Intent intent) { updateWifiIcons(); } - private void updateWifiIcons() { + protected void updateWifiIcons() { if (mWifiConnected) { mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel]; mQSWifiIconId = WifiIcons.QS_WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel]; @@ -959,7 +989,7 @@ private String huntForSsid(WifiInfo info) { // ===== Wimax =================================================================== - private final void updateWimaxState(Intent intent) { + protected final void updateWimaxState(Intent intent) { final String action = intent.getAction(); boolean wasConnected = mWimaxConnected; if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION)) { @@ -983,7 +1013,7 @@ private final void updateWimaxState(Intent intent) { updateWimaxIcons(); } - private void updateWimaxIcons() { + protected void updateWimaxIcons() { if (mIsWimaxEnabled) { if (mWimaxConnected) { if (mWimaxIdle) @@ -1003,7 +1033,7 @@ private void updateWimaxIcons() { // ===== Full or limited Internet connectivity ================================== - private void updateConnectivity(Intent intent) { + protected void updateConnectivity(Intent intent) { if (CHATTY) { Slog.d(TAG, "updateConnectivity: intent=" + intent); } @@ -1181,6 +1211,7 @@ void refreshViews() { mAirplaneIconId = R.drawable.stat_sys_signal_flightmode; mPhoneSignalIconId = mDataSignalIconId = mDataTypeIconId = mQSDataTypeIconId = 0; mQSPhoneSignalIconId = 0; + mNoSimIconId = 0; // combined values from connected wifi take precedence over airplane mode if (mWifiConnected) { @@ -1243,6 +1274,7 @@ void refreshViews() { + " mDataSignalIconId=0x" + Integer.toHexString(mDataSignalIconId) + " mDataTypeIconId=0x" + Integer.toHexString(mDataTypeIconId) + " mQSDataTypeIconId=0x" + Integer.toHexString(mQSDataTypeIconId) + + " mNoSimIconId=0x" + Integer.toHexString(mNoSimIconId) + " mWifiIconId=0x" + Integer.toHexString(mWifiIconId) + " mQSWifiIconId=0x" + Integer.toHexString(mQSWifiIconId) + " mBluetoothTetherIconId=0x" + Integer.toHexString(mBluetoothTetherIconId)); @@ -1256,7 +1288,7 @@ void refreshViews() { || mLastAirplaneMode != mAirplaneMode || mLastLocale != mLocale || mLastEtherIconId != mEtherIconId - || mLastAirplaneMode != mAirplaneMode) + || mLastSimIconId != mNoSimIconId) { // NB: the mLast*s will be updated later for (SignalCluster cluster : mSignalClusters) { @@ -1302,6 +1334,10 @@ void refreshViews() { } } + if (mLastSimIconId != mNoSimIconId) { + mLastSimIconId = mNoSimIconId; + } + // the wifi icon on phones if (mLastWifiIconId != mWifiIconId) { mLastWifiIconId = mWifiIconId; @@ -1561,7 +1597,7 @@ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(""); } - private String getResourceName(int resId) { + protected String getResourceName(int resId) { if (resId != 0) { final Resources res = mContext.getResources(); try { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java index f46ff7b084dd0..9a4d5a9b7a22b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -1,5 +1,8 @@ /* * Copyright (C) 2010 The Android Open Source Project + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Not a Contribution. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,6 +46,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.provider.Settings; +import android.telephony.MSimTelephonyManager; import android.text.TextUtils; import android.util.Pair; import android.util.Slog; @@ -69,6 +73,7 @@ import com.android.systemui.statusbar.BaseStatusBar; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.DoNotDisturb; +import com.android.systemui.statusbar.MSimSignalClusterView; import com.android.systemui.statusbar.NotificationData; import com.android.systemui.statusbar.NotificationData.Entry; import com.android.systemui.statusbar.SignalClusterView; @@ -81,6 +86,7 @@ import com.android.systemui.statusbar.policy.LocationController; import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.NotificationRowLayout; +import com.android.systemui.statusbar.policy.MSimNetworkController; import com.android.systemui.statusbar.policy.Prefs; import java.io.FileDescriptor; @@ -161,6 +167,7 @@ public class TabletStatusBar extends BaseStatusBar implements LocationController mLocationController; NetworkController mNetworkController; DoNotDisturb mDoNotDisturb; + MSimNetworkController mMSimNetworkController; ViewGroup mBarContents; @@ -278,24 +285,41 @@ protected void addPanelWindows() { // mobile and data icons final ImageView mobileRSSI = (ImageView)mNotificationPanel.findViewById(R.id.mobile_signal); - if (mobileRSSI != null) { - mNetworkController.addPhoneSignalIconView(mobileRSSI); - } final ImageView wifiRSSI = (ImageView)mNotificationPanel.findViewById(R.id.wifi_signal); - if (wifiRSSI != null) { - mNetworkController.addWifiIconView(wifiRSSI); - } - mNetworkController.addWifiLabelView( - (TextView)mNotificationPanel.findViewById(R.id.wifi_text)); - - mNetworkController.addDataTypeIconView( - (ImageView)mNotificationPanel.findViewById(R.id.mobile_type)); - mNetworkController.addMobileLabelView( - (TextView)mNotificationPanel.findViewById(R.id.mobile_text)); - mNetworkController.addCombinedLabelView( - (TextView)mBarContents.findViewById(R.id.network_text)); + if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) { + if (mobileRSSI != null) { + mMSimNetworkController.addPhoneSignalIconView(mobileRSSI); + } + if (wifiRSSI != null) { + mMSimNetworkController.addWifiIconView(wifiRSSI); + } + mMSimNetworkController.addWifiLabelView( + (TextView)mNotificationPanel.findViewById(R.id.wifi_text)); + + mMSimNetworkController.addDataTypeIconView( + (ImageView)mNotificationPanel.findViewById(R.id.mobile_type)); + mMSimNetworkController.addMobileLabelView( + (TextView)mNotificationPanel.findViewById(R.id.mobile_text)); + mMSimNetworkController.addCombinedLabelView( + (TextView)mBarContents.findViewById(R.id.network_text)); + } else { + if (mobileRSSI != null) { + mNetworkController.addPhoneSignalIconView(mobileRSSI); + } + if (wifiRSSI != null) { + mNetworkController.addWifiIconView(wifiRSSI); + } + mNetworkController.addWifiLabelView( + (TextView)mNotificationPanel.findViewById(R.id.wifi_text)); + mNetworkController.addDataTypeIconView( + (ImageView)mNotificationPanel.findViewById(R.id.mobile_type)); + mNetworkController.addMobileLabelView( + (TextView)mNotificationPanel.findViewById(R.id.mobile_text)); + mNetworkController.addCombinedLabelView( + (TextView)mBarContents.findViewById(R.id.network_text)); + } mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel); WindowManager.LayoutParams lp = mNotificationPanelParams = new WindowManager.LayoutParams( @@ -570,12 +594,23 @@ protected View makeStatusBarView() { mBluetoothController = new BluetoothController(mContext); mBluetoothController.addIconView((ImageView)sb.findViewById(R.id.bluetooth)); - mNetworkController = new NetworkController(mContext); - mSignalView = (SignalClusterView) sb.findViewById(R.id.signal_cluster); - mNetworkController.addSignalCluster(mSignalView); - mClock = (Clock) sb.findViewById(R.id.clock); + if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) { + final MSimSignalClusterView mSimSignalCluster = + (MSimSignalClusterView)sb.findViewById(R.id.msim_signal_cluster); + + mMSimNetworkController = new MSimNetworkController(mContext); + for(int i=0; i < MSimTelephonyManager.getDefault().getPhoneCount(); i++) { + mMSimNetworkController.addSignalCluster(mSimSignalCluster, i); + } + } else { + mSignalCluster = (SignalClusterView)sb.findViewById(R.id.signal_cluster); + + mNetworkController = new NetworkController(mContext); + mNetworkController.addSignalCluster(signalCluster); + } + // The navigation buttons mBackButton = (ImageView)sb.findViewById(R.id.back); mNavigationArea = (ViewGroup) sb.findViewById(R.id.navigationArea); @@ -1600,8 +1635,15 @@ public void onReceive(Context context, Intent intent) { public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.print("mDisabled=0x"); pw.println(Integer.toHexString(mDisabled)); - pw.println("mNetworkController:"); - mNetworkController.dump(fd, pw, args); + if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) { + pw.println("mMSimNetworkController:"); + for(int i=0; i < MSimTelephonyManager.getDefault().getPhoneCount(); i++) { + mMSimNetworkController.dump(fd, pw, args, i); + } + } else { + pw.println("mNetworkController:"); + mNetworkController.dump(fd, pw, args); + } } @Override From 29b593eef54cb6ff69319f438b98fe9bc5d2998e Mon Sep 17 00:00:00 2001 From: Uma Maheswari Ramalingam Date: Tue, 15 Nov 2011 16:18:07 -0800 Subject: [PATCH 050/204] Fix for data and roaming icons - Enable data connected flag based on the data state. - Do not display data icon in data connected state if radio type is unknown - Display data icon independent of voice service state i.e even if voice network is unavailable - Show cdma roaming indicators if either voice or data is roaming. - Cleanup roaming indicator default values. Set default CDMA Eri index to roaming off - Show service if either voice/data is in service if ro.config.combined_signal is true - Consider eri only when in service - Add in service check to isCdmaEri. roaming related information in registration state will not be valid during out of service. CRs-Fixed: 285986, 303275, 326204, 326634, 333008, 339297 Change-Id: I915421a6f5906d80ed5b8dd9c433115ad5df1f14 --- .../statusbar/policy/NetworkController.java | 73 ++++++++++++------- .../java/android/telephony/ServiceState.java | 2 +- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 6b5ea069e5faa..3627456519a8d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -35,6 +35,7 @@ import android.os.Message; import android.os.Messenger; import android.os.RemoteException; +import android.os.SystemProperties; import android.provider.Settings; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; @@ -62,8 +63,8 @@ public class NetworkController extends BroadcastReceiver { // debug static final String TAG = "StatusBar.NetworkController"; - static final boolean DEBUG = false; - static final boolean CHATTY = false; // additional diagnostics, but not logspew + static final boolean DEBUG = true; + static final boolean CHATTY = true; // additional diagnostics, but not logspew // telephony boolean mHspaDataDistinguishable; @@ -476,9 +477,19 @@ public void onSignalStrengthsChanged(SignalStrength signalStrength) { @Override public void onServiceStateChanged(ServiceState state) { if (DEBUG) { - Slog.d(TAG, "onServiceStateChanged state=" + state.getState()); + Slog.d(TAG, "onServiceStateChanged state=" + state); } mServiceState = state; + if (SystemProperties.getBoolean("ro.config.combined_signal", true)) { + /* + * if combined_signal is set to true only then consider data + * service state for signal display + */ + mDataServiceState = mServiceState.getDataRegState(); + if (DEBUG) { + Slog.d(TAG, "Combining data service state" + mDataServiceState + "for signal"); + } + } updateTelephonySignalStrength(); updateDataNetType(); updateDataIcon(); @@ -578,14 +589,18 @@ private void refreshLocale() { } private final void updateTelephonySignalStrength() { - if (!hasService()) { - if (CHATTY) Slog.d(TAG, "updateTelephonySignalStrength: !hasService()"); + if (!hasService() && + (mDataServiceState != ServiceState.STATE_IN_SERVICE)) { + if (DEBUG) Slog.d(TAG, " No service"); mPhoneSignalIconId = R.drawable.stat_sys_signal_null; mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal; mDataSignalIconId = R.drawable.stat_sys_signal_null; } else { - if (mSignalStrength == null) { - if (CHATTY) Slog.d(TAG, "updateTelephonySignalStrength: mSignalStrength == null"); + if ((mSignalStrength == null) || (mServiceState == null)) { + if (DEBUG) { + Slog.d(TAG, " Null object, mSignalStrength= " + mSignalStrength + + " mServiceState " + mServiceState); + } mPhoneSignalIconId = R.drawable.stat_sys_signal_null; mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal; mDataSignalIconId = R.drawable.stat_sys_signal_null; @@ -603,20 +618,13 @@ private final void updateTelephonySignalStrength() { mLastSignalLevel = iconLevel = mSignalStrength.getLevel(); } - if (isCdma()) { - if (isCdmaEri()) { - iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition]; - } else { - iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition]; - } + // Though mPhone is a Manager, this call is not an IPC + if ((isCdma() && isCdmaEri()) || mPhone.isNetworkRoaming()) { + iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition]; } else { - // Though mPhone is a Manager, this call is not an IPC - if (mPhone.isNetworkRoaming()) { - iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition]; - } else { - iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition]; - } + iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition]; } + mPhoneSignalIconId = iconList[iconLevel]; mQSPhoneSignalIconId = TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[mInetCondition][iconLevel]; @@ -638,6 +646,9 @@ private final void updateDataNetType() { } else { switch (mDataNetType) { case TelephonyManager.NETWORK_TYPE_UNKNOWN: + if (DEBUG) { + Slog.e(TAG, "updateDataNetType NETWORK_TYPE_UNKNOWN"); + } if (!mShowAtLeastThreeGees) { mDataIconList = TelephonyIcons.DATA_G[mInetCondition]; mDataTypeIconId = 0; @@ -745,7 +756,7 @@ private final void updateDataNetType() { R.string.accessibility_data_connection_lte); } break; - default: + case TelephonyManager.NETWORK_TYPE_GPRS: if (!mShowAtLeastThreeGees) { mDataIconList = TelephonyIcons.DATA_G[mInetCondition]; mDataTypeIconId = R.drawable.stat_sys_data_connected_g; @@ -760,6 +771,13 @@ private final void updateDataNetType() { R.string.accessibility_data_connection_3g); } break; + default: + if (DEBUG) { + Slog.e(TAG, "updateDataNetType unknown radio:" + mDataNetType); + } + mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + mDataTypeIconId = 0; + break; } } @@ -775,7 +793,8 @@ private final void updateDataNetType() { } boolean isCdmaEri() { - if (mServiceState != null) { + if ((mServiceState != null) + && (hasService() || (mDataServiceState == ServiceState.STATE_IN_SERVICE))) { final int iconIndex = mServiceState.getCdmaEriIconIndex(); if (iconIndex != EriInfo.ROAMING_INDICATOR_OFF) { final int iconMode = mServiceState.getCdmaEriIconMode(); @@ -799,14 +818,16 @@ private final void updateSimIcon() { } private final void updateDataIcon() { - int iconId; + int iconId = 0; boolean visible = true; - - if (!isCdma()) { + if (mDataNetType == TelephonyManager.NETWORK_TYPE_UNKNOWN) { + // If data network type is unknown do not display data icon + visible = false; + } else if (!isCdma()) { // GSM case, we have to check also the sim state if (mSimState == IccCardConstants.State.READY || mSimState == IccCardConstants.State.UNKNOWN) { - if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) { + if (mDataState == TelephonyManager.DATA_CONNECTED) { switch (mDataActivity) { case TelephonyManager.DATA_ACTIVITY_IN: iconId = mDataIconList[1]; @@ -832,7 +853,7 @@ private final void updateDataIcon() { } } else { // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT - if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) { + if (mDataState == TelephonyManager.DATA_CONNECTED) { switch (mDataActivity) { case TelephonyManager.DATA_ACTIVITY_IN: iconId = mDataIconList[1]; diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index a5f293284c6d8..2dbfb298b0f1e 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -188,7 +188,7 @@ public class ServiceState implements Parcelable { private int mSystemId; private int mCdmaRoamingIndicator; private int mCdmaDefaultRoamingIndicator; - private int mCdmaEriIconIndex; + private int mCdmaEriIconIndex = 1; //EriInfo.ROAMING_INDICATOR_OFF; private int mCdmaEriIconMode; /** From 622b7b6aa5c2926ce7894b6b09e87a3daa3291e7 Mon Sep 17 00:00:00 2001 From: Ravi Paluri Date: Mon, 8 Jul 2013 16:05:44 +0530 Subject: [PATCH 051/204] Ims: Fix for Phone App crash and NullPtrException in getCountryIso API When back to back VOLTE calls are made, sometimes next MO VOLTE call is failing due to a NullPointerException. The issue is because of unexpected value in getting the current country code. Added null check for detector.detectCountry(), if this function call fails, then CountryIso will be picked up based on the Locale CRs-Fixed: 478645, 490472 Change-Id: I9f35fe959fc072bf59a6aabc6c17dc4162426721 --- .../android/telephony/PhoneNumberUtils.java | 18 ++++++++++++------ .../android/internal/telephony/CallerInfo.java | 2 ++ .../telephony/CallerInfoAsyncQuery.java | 13 ++++++++++--- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index e7ddd9cd7e69a..1a6fae278a168 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -29,6 +29,7 @@ import android.content.Intent; import android.database.Cursor; import android.location.CountryDetector; +import android.location.Country; import android.net.Uri; import android.os.SystemProperties; import android.provider.Contacts; @@ -1812,16 +1813,21 @@ public static boolean isPotentialLocalEmergencyNumber(String number, Context con private static boolean isLocalEmergencyNumberInternal(String number, Context context, boolean useExactMatch) { - String countryIso; + String countryIso = null; + Country country; CountryDetector detector = (CountryDetector) context.getSystemService( Context.COUNTRY_DETECTOR); - if (detector != null) { - countryIso = detector.detectCountry().getCountryIso(); + if ((detector != null) && ((country = detector.detectCountry()) != null)) { + countryIso = country.getCountryIso(); } else { Locale locale = context.getResources().getConfiguration().locale; - countryIso = locale.getCountry(); - Rlog.w(LOG_TAG, "No CountryDetector; falling back to countryIso based on locale: " - + countryIso); + if(locale != null) { + countryIso = locale.getCountry(); + Rlog.w(LOG_TAG, "No CountryDetector; falling back to countryIso based on locale: " + + countryIso); + } else { + countryIso = "US"; //default value is "US" + } } return isEmergencyNumberInternal(number, countryIso, useExactMatch); } diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java index 4e9434682ffe6..d5423fd154e0e 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfo.java +++ b/telephony/java/com/android/internal/telephony/CallerInfo.java @@ -550,6 +550,8 @@ private static String getGeoDescription(Context context, String number) { if (VDBG) Rlog.v(TAG, "- parsed number: " + pn); } catch (NumberParseException e) { Rlog.w(TAG, "getGeoDescription: NumberParseException for incoming number '" + number + "'"); + } catch (Exception e) { + Log.w(TAG, "Exception Caught" + e); } if (pn != null) { diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java index dd5f6444c3d79..bf1cf4a060091 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java +++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java @@ -21,6 +21,7 @@ import android.database.Cursor; import android.database.SQLException; import android.location.CountryDetector; +import android.location.Country; import android.net.Uri; import android.os.Handler; import android.os.Looper; @@ -271,11 +272,17 @@ protected void onQueryComplete(int token, Object cookie, Cursor cursor) { // Use the number entered by the user for display. if (!TextUtils.isEmpty(cw.number)) { + Country country; CountryDetector detector = (CountryDetector) mQueryContext.getSystemService( Context.COUNTRY_DETECTOR); - mCallerInfo.phoneNumber = PhoneNumberUtils.formatNumber(cw.number, - mCallerInfo.normalizedNumber, - detector.detectCountry().getCountryIso()); + if (detector != null) { + country = detector.detectCountry(); + if (country != null) { + mCallerInfo.phoneNumber = PhoneNumberUtils.formatNumber(cw.number, + mCallerInfo.normalizedNumber, + country.getCountryIso()); + } + } } } From c8cb5b9a62a70c8f9a3d3c963f15e60ae78b601c Mon Sep 17 00:00:00 2001 From: Venkat Ram Prakash Kotni Date: Mon, 1 Apr 2013 10:20:09 +0530 Subject: [PATCH 052/204] Telephony: Add TD-SCDMA support Add network mode TD-SCDMA to the list of supported network modes. CRs-Fixed: 479310 Change-Id: I132ac6a2108ef641ce4e71942a5c057a8df8e76c --- .../java/android/telephony/TelephonyManager.java | 10 ++++++++++ .../com/android/internal/telephony/RILConstants.java | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 333a078d29f10..6f8ee227541ff 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -417,12 +417,22 @@ public static int getPhoneType(int networkMode) { case RILConstants.NETWORK_MODE_GSM_UMTS: case RILConstants.NETWORK_MODE_LTE_GSM_WCDMA: case RILConstants.NETWORK_MODE_LTE_WCDMA: + case RILConstants.NETWORK_MODE_TD_SCDMA_ONLY: + case RILConstants.NETWORK_MODE_TD_SCDMA_WCDMA: + case RILConstants.NETWORK_MODE_TD_SCDMA_LTE: + case RILConstants.NETWORK_MODE_TD_SCDMA_GSM: + case RILConstants.NETWORK_MODE_TD_SCDMA_GSM_LTE: + case RILConstants.NETWORK_MODE_TD_SCDMA_GSM_WCDMA: + case RILConstants.NETWORK_MODE_TD_SCDMA_WCDMA_LTE: + case RILConstants.NETWORK_MODE_TD_SCDMA_GSM_WCDMA_LTE: return PhoneConstants.PHONE_TYPE_GSM; // Use CDMA Phone for the global mode including CDMA case RILConstants.NETWORK_MODE_GLOBAL: case RILConstants.NETWORK_MODE_LTE_CDMA_EVDO: case RILConstants.NETWORK_MODE_LTE_CMDA_EVDO_GSM_WCDMA: + case RILConstants.NETWORK_MODE_TD_SCDMA_CDMA_EVDO_GSM_WCDMA: + case RILConstants.NETWORK_MODE_TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA: return PhoneConstants.PHONE_TYPE_CDMA; case RILConstants.NETWORK_MODE_LTE_ONLY: diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 4470f4dfbbb51..7fc1cb3bd1376 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -86,6 +86,17 @@ class C */ int NETWORK_MODE_LTE_CMDA_EVDO_GSM_WCDMA = 10; /* LTE, CDMA, EvDo, GSM/WCDMA */ int NETWORK_MODE_LTE_ONLY = 11; /* LTE Only mode. */ int NETWORK_MODE_LTE_WCDMA = 12; /* LTE/WCDMA */ + int NETWORK_MODE_TD_SCDMA_ONLY = 13; /* TD-SCDMA only */ + int NETWORK_MODE_TD_SCDMA_WCDMA = 14; /* TD-SCDMA and WCDMA */ + int NETWORK_MODE_TD_SCDMA_LTE = 15; /* TD-SCDMA and LTE */ + int NETWORK_MODE_TD_SCDMA_GSM = 16; /* TD-SCDMA and GSM */ + int NETWORK_MODE_TD_SCDMA_GSM_LTE = 17; /* TD-SCDMA,GSM and LTE */ + int NETWORK_MODE_TD_SCDMA_GSM_WCDMA = 18; /* TD-SCDMA, GSM/WCDMA */ + int NETWORK_MODE_TD_SCDMA_WCDMA_LTE = 19; /* TD-SCDMA, WCDMA and LTE */ + int NETWORK_MODE_TD_SCDMA_GSM_WCDMA_LTE = 20; /* TD-SCDMA, GSM/WCDMA and LTE */ + int NETWORK_MODE_TD_SCDMA_CDMA_EVDO_GSM_WCDMA = 21; /*TD-SCDMA,EvDo,CDMA,GSM/WCDMA*/ + int NETWORK_MODE_TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA = 22; /* TD-SCDMA/LTE/GSM/WCDMA, CDMA, and + EvDo */ int PREFERRED_NETWORK_MODE = NETWORK_MODE_WCDMA_PREF; int CDMA_CELL_BROADCAST_SMS_DISABLED = 1; From 7db863035ae90551014f7440102dbd9fc333163b Mon Sep 17 00:00:00 2001 From: Yashdev Singh Date: Fri, 7 Jun 2013 23:10:32 +0530 Subject: [PATCH 053/204] Telephony: Add RIL request and event for OMH support Change-Id: I8f68d6d9e1e188a2c2295a814376dccaaad5ec24 --- .../java/com/android/internal/telephony/DctConstants.java | 5 ++++- .../java/com/android/internal/telephony/RILConstants.java | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java index 39b48985e5219..1ef46fa724230 100644 --- a/telephony/java/com/android/internal/telephony/DctConstants.java +++ b/telephony/java/com/android/internal/telephony/DctConstants.java @@ -1,6 +1,8 @@ /* * Copyright (C) 2012 The Android Open Source Project - * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. + * + * Not a Contribution. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -95,6 +97,7 @@ public enum Activity { public static final int EVENT_DISCONNECT_DC_RETRYING = BASE + 34; public static final int EVENT_DATA_SETUP_COMPLETE_ERROR = BASE + 35; public static final int EVENT_TETHERED_MODE_STATE_CHANGED = BASE + 36; + public static final int EVENT_MODEM_DATA_PROFILE_READY= BASE + 37; public static final int CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA = BASE + 38; public static final int CMD_ENABLE_MOBILE_PROVISIONING = BASE + 39; diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 7fc1cb3bd1376..d40acf9415e99 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -295,6 +295,7 @@ class C */ int RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE = 110; int RIL_REQUEST_IMS_REGISTRATION_STATE = 111; int RIL_REQUEST_IMS_SEND_SMS = 112; + int RIL_REQUEST_GET_DATA_CALL_PROFILE = 113; int RIL_REQUEST_SET_UICC_SUBSCRIPTION = 114; int RIL_REQUEST_SET_DATA_SUBSCRIPTION = 115; int RIL_REQUEST_GET_UICC_SUBSCRIPTION = 116; From c1f81610370f81a8da6f21d88328e6b791e07caf Mon Sep 17 00:00:00 2001 From: mengsun Date: Thu, 18 Jul 2013 13:47:45 +0800 Subject: [PATCH 054/204] Telephony(MSIM): Set priority when send sms Add the priority support in 3gpp2 text message Change-Id: I27e92709a04a89c125424f99c2c61fbf6802c6b1 --- .../com/android/internal/telephony/ISms.aidl | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl index c9e73be78e956..4e4136ffdbf33 100644 --- a/telephony/java/com/android/internal/telephony/ISms.aidl +++ b/telephony/java/com/android/internal/telephony/ISms.aidl @@ -120,6 +120,35 @@ interface ISms { void sendText(String callingPkg, in String destAddr, in String scAddr, in String text, in PendingIntent sentIntent, in PendingIntent deliveryIntent); + /** + * Send an SMS. + * + * @param destAddr the address to send the message to + * @param smsc the SMSC to send the message through, or NULL for the + * default SMSC + * @param text the body of the message to send + * @param sentIntent if not NULL this PendingIntent is + * broadcast when the message is sucessfully sent, or failed. + * The result code will be Activity.RESULT_OK for success, + * or one of these errors:
+ * RESULT_ERROR_GENERIC_FAILURE
+ * RESULT_ERROR_RADIO_OFF
+ * RESULT_ERROR_NULL_PDU
+ * For RESULT_ERROR_GENERIC_FAILURE the sentIntent may include + * the extra "errorCode" containing a radio technology specific value, + * generally only useful for troubleshooting.
+ * The per-application based SMS control checks sentIntent. If sentIntent + * is NULL the caller will be checked against all unknown applications, + * which cause smaller number of SMS to be sent in checking period. + * @param deliveryIntent if not NULL this PendingIntent is + * broadcast when the message is delivered to the recipient. The + * raw pdu of the status report is in the extended data ("pdu"). + * @param priority Priority level of the message + */ + void sendTextWithPriority(in String destAddr, in String scAddr, in String text, + in PendingIntent sentIntent, in PendingIntent deliveryIntent, + in int priority); + /** * Send a multi-part text based SMS. * From 45dcf94b38c031c6500fe076fd9dac6e7049a547 Mon Sep 17 00:00:00 2001 From: Rakesh Pallerla Date: Tue, 4 Jun 2013 17:21:53 +0530 Subject: [PATCH 055/204] Telephony(MSIM): MultiSim support for PIN/PUK & Operator Name. -> Add CarrierText, SimPinView and SimPukView classes for MSIM. -> Add support to Display Multiple operator name. -> Add Support for Multiple PIN/PUK Lock screens. -> Overload few Keyguard methods to take sub info. Change-Id: I500129a5dc09adcb2cd8eb664d30ae2e8bad2642 --- .../res/drawable-hdpi/sym_keyboard_cancel.png | Bin 0 -> 573 bytes .../res/drawable-ldpi/sym_keyboard_cancel.png | Bin 0 -> 573 bytes .../res/drawable-mdpi/sym_keyboard_cancel.png | Bin 0 -> 573 bytes .../drawable-xhdpi/sym_keyboard_cancel.png | Bin 0 -> 573 bytes .../keyguard_emergency_carrier_area.xml | 9 + .../res/layout/msim_keyguard_carrier_area.xml | 41 +++ .../res/layout/msim_keyguard_sim_pin_view.xml | 236 ++++++++++++++++++ .../res/layout/msim_keyguard_sim_puk_view.xml | 231 +++++++++++++++++ core/res/res/values/strings.xml | 6 + core/res/res/values/symbols.xml | 14 ++ .../policy/impl/keyguard/CarrierText.java | 8 +- .../impl/keyguard/KeyguardHostView.java | 36 ++- .../impl/keyguard/KeyguardSecurityModel.java | 19 +- .../impl/keyguard/KeyguardSimPinView.java | 22 +- .../impl/keyguard/KeyguardSimPukView.java | 25 +- .../impl/keyguard/KeyguardUpdateMonitor.java | 170 +++++++++++-- .../KeyguardUpdateMonitorCallback.java | 21 ++ .../impl/keyguard/KeyguardViewMediator.java | 33 ++- .../impl/keyguard/msim/MSimCarrierText.java | 101 ++++++++ .../keyguard/msim/MSimKeyguardSimPinView.java | 195 +++++++++++++++ .../keyguard/msim/MSimKeyguardSimPukView.java | 169 +++++++++++++ 21 files changed, 1282 insertions(+), 54 deletions(-) create mode 100644 core/res/res/drawable-hdpi/sym_keyboard_cancel.png create mode 100755 core/res/res/drawable-ldpi/sym_keyboard_cancel.png create mode 100644 core/res/res/drawable-mdpi/sym_keyboard_cancel.png create mode 100644 core/res/res/drawable-xhdpi/sym_keyboard_cancel.png create mode 100644 core/res/res/layout/msim_keyguard_carrier_area.xml create mode 100644 core/res/res/layout/msim_keyguard_sim_pin_view.xml create mode 100644 core/res/res/layout/msim_keyguard_sim_puk_view.xml create mode 100644 policy/src/com/android/internal/policy/impl/keyguard/msim/MSimCarrierText.java create mode 100644 policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPinView.java create mode 100755 policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPukView.java diff --git a/core/res/res/drawable-hdpi/sym_keyboard_cancel.png b/core/res/res/drawable-hdpi/sym_keyboard_cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..70258d5c7a7bb7fbd8e1351767ef380e593155c7 GIT binary patch literal 573 zcmV-D0>b@?P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*n* z2_!22XtO*300F&8L_t(Y$L-Y5i;Ynj2k__InLF-`1s0d3LdsZJC@BkN6dEjSl$BUp zSW>c*tv^5(VyC8PD2fu3@+&e~SZGK}HWZ9kkz|_ zrR5^nhX)0PFQ8q@+l_lUX9@>9#2?}-UgISCtB`q&^%clWVhaYb2&Zta1DQwIlof7g z#m5Rcqj-s}xhqx`KNH(<9~;oba$LfRDr7#R)q~VSc+-K*n$p=4Oc(YO-DVLtv95Hs z46o*l3|3-1x6UkPI*>`-dK{lH)TPcxe9!9#X3Dj?x!JRb7_K13`G~k15vwDjFCv-| z@!P{wO8#-a8xhe?DfOq6`cg`b^b3tD?Q*oD0emYeh>hhR`jh-6WhOA%rOqwv@72v( zxP#N#nw#00w->EB8^Gb5zcvqgFJyM%MK+Ux4hArSx7dq?d5vKFuViv?5XbQ}+u?g$ zE&gD3mnT`FDIDsBOy2J)SnqQjD8)D9I;QiC-6*|9)TmLT#(#;Qol}F}9ZS<`00000 LNkvXXu0mjfAGGz& literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-ldpi/sym_keyboard_cancel.png b/core/res/res/drawable-ldpi/sym_keyboard_cancel.png new file mode 100755 index 0000000000000000000000000000000000000000..70258d5c7a7bb7fbd8e1351767ef380e593155c7 GIT binary patch literal 573 zcmV-D0>b@?P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*n* z2_!22XtO*300F&8L_t(Y$L-Y5i;Ynj2k__InLF-`1s0d3LdsZJC@BkN6dEjSl$BUp zSW>c*tv^5(VyC8PD2fu3@+&e~SZGK}HWZ9kkz|_ zrR5^nhX)0PFQ8q@+l_lUX9@>9#2?}-UgISCtB`q&^%clWVhaYb2&Zta1DQwIlof7g z#m5Rcqj-s}xhqx`KNH(<9~;oba$LfRDr7#R)q~VSc+-K*n$p=4Oc(YO-DVLtv95Hs z46o*l3|3-1x6UkPI*>`-dK{lH)TPcxe9!9#X3Dj?x!JRb7_K13`G~k15vwDjFCv-| z@!P{wO8#-a8xhe?DfOq6`cg`b^b3tD?Q*oD0emYeh>hhR`jh-6WhOA%rOqwv@72v( zxP#N#nw#00w->EB8^Gb5zcvqgFJyM%MK+Ux4hArSx7dq?d5vKFuViv?5XbQ}+u?g$ zE&gD3mnT`FDIDsBOy2J)SnqQjD8)D9I;QiC-6*|9)TmLT#(#;Qol}F}9ZS<`00000 LNkvXXu0mjfAGGz& literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-mdpi/sym_keyboard_cancel.png b/core/res/res/drawable-mdpi/sym_keyboard_cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..70258d5c7a7bb7fbd8e1351767ef380e593155c7 GIT binary patch literal 573 zcmV-D0>b@?P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*n* z2_!22XtO*300F&8L_t(Y$L-Y5i;Ynj2k__InLF-`1s0d3LdsZJC@BkN6dEjSl$BUp zSW>c*tv^5(VyC8PD2fu3@+&e~SZGK}HWZ9kkz|_ zrR5^nhX)0PFQ8q@+l_lUX9@>9#2?}-UgISCtB`q&^%clWVhaYb2&Zta1DQwIlof7g z#m5Rcqj-s}xhqx`KNH(<9~;oba$LfRDr7#R)q~VSc+-K*n$p=4Oc(YO-DVLtv95Hs z46o*l3|3-1x6UkPI*>`-dK{lH)TPcxe9!9#X3Dj?x!JRb7_K13`G~k15vwDjFCv-| z@!P{wO8#-a8xhe?DfOq6`cg`b^b3tD?Q*oD0emYeh>hhR`jh-6WhOA%rOqwv@72v( zxP#N#nw#00w->EB8^Gb5zcvqgFJyM%MK+Ux4hArSx7dq?d5vKFuViv?5XbQ}+u?g$ zE&gD3mnT`FDIDsBOy2J)SnqQjD8)D9I;QiC-6*|9)TmLT#(#;Qol}F}9ZS<`00000 LNkvXXu0mjfAGGz& literal 0 HcmV?d00001 diff --git a/core/res/res/drawable-xhdpi/sym_keyboard_cancel.png b/core/res/res/drawable-xhdpi/sym_keyboard_cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..70258d5c7a7bb7fbd8e1351767ef380e593155c7 GIT binary patch literal 573 zcmV-D0>b@?P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*n* z2_!22XtO*300F&8L_t(Y$L-Y5i;Ynj2k__InLF-`1s0d3LdsZJC@BkN6dEjSl$BUp zSW>c*tv^5(VyC8PD2fu3@+&e~SZGK}HWZ9kkz|_ zrR5^nhX)0PFQ8q@+l_lUX9@>9#2?}-UgISCtB`q&^%clWVhaYb2&Zta1DQwIlof7g z#m5Rcqj-s}xhqx`KNH(<9~;oba$LfRDr7#R)q~VSc+-K*n$p=4Oc(YO-DVLtv95Hs z46o*l3|3-1x6UkPI*>`-dK{lH)TPcxe9!9#X3Dj?x!JRb7_K13`G~k15vwDjFCv-| z@!P{wO8#-a8xhe?DfOq6`cg`b^b3tD?Q*oD0emYeh>hhR`jh-6WhOA%rOqwv@72v( zxP#N#nw#00w->EB8^Gb5zcvqgFJyM%MK+Ux4hArSx7dq?d5vKFuViv?5XbQ}+u?g$ zE&gD3mnT`FDIDsBOy2J)SnqQjD8)D9I;QiC-6*|9)TmLT#(#;Qol}F}9ZS<`00000 LNkvXXu0mjfAGGz& literal 0 HcmV?d00001 diff --git a/core/res/res/layout/keyguard_emergency_carrier_area.xml b/core/res/res/layout/keyguard_emergency_carrier_area.xml index b8a7654c8dce6..8a9f5dc842a18 100644 --- a/core/res/res/layout/keyguard_emergency_carrier_area.xml +++ b/core/res/res/layout/keyguard_emergency_carrier_area.xml @@ -2,6 +2,8 @@ + + + + + + + + + diff --git a/core/res/res/layout/msim_keyguard_sim_pin_view.xml b/core/res/res/layout/msim_keyguard_sim_pin_view.xml new file mode 100644 index 0000000000000..11e95b9c0cfee --- /dev/null +++ b/core/res/res/layout/msim_keyguard_sim_pin_view.xml @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/layout/msim_keyguard_sim_puk_view.xml b/core/res/res/layout/msim_keyguard_sim_puk_view.xml new file mode 100644 index 0000000000000..213e6bf8ea704 --- /dev/null +++ b/core/res/res/layout/msim_keyguard_sim_puk_view.xml @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 40910396c0c84..a07123190853e 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4148,4 +4148,10 @@ SS request is modified to USSD request. SS request is modified to new SS request. + + + SUB:%d : %s. + + + %s, %s diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 45c0ba243b071..042fb1fe3b2bd 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1402,6 +1402,7 @@ + @@ -1879,6 +1880,19 @@ + + + + + + + + + + + + + diff --git a/policy/src/com/android/internal/policy/impl/keyguard/CarrierText.java b/policy/src/com/android/internal/policy/impl/keyguard/CarrierText.java index 49d7afcdf6ab6..ab2c2edc92c2e 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/CarrierText.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/CarrierText.java @@ -1,6 +1,9 @@ /* * Copyright (C) 2012 The Android Open Source Project * + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * 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 @@ -92,6 +95,9 @@ protected void onFinishInflate() { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + if (KeyguardUpdateMonitor.sIsMultiSimEnabled) { + return; + } KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mCallback); } @@ -110,7 +116,7 @@ protected void onDetachedFromWindow() { * @param spn * @return */ - private CharSequence getCarrierTextForSimState(IccCardConstants.State simState, + protected CharSequence getCarrierTextForSimState(IccCardConstants.State simState, CharSequence plmn, CharSequence spn) { CharSequence carrierText = null; StatusMode status = getStatusForIccState(simState); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java index a1ea19af0a3fc..f2f0a0f4051d0 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java @@ -1,6 +1,9 @@ /* * Copyright (C) 2012 The Android Open Source Project * + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * 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 @@ -52,6 +55,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.telephony.MSimTelephonyManager; import android.util.AttributeSet; import android.util.Log; import android.util.Slog; @@ -60,10 +64,12 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; +import android.view.ViewStub; import android.view.WindowManager; import android.view.animation.AnimationUtils; import android.widget.RemoteViews.OnClickHandler; + import com.android.internal.R; import com.android.internal.app.ThemeUtils; import com.android.internal.policy.impl.keyguard.KeyguardSecurityModel.SecurityMode; @@ -985,6 +991,12 @@ private KeyguardSecurityView getSecurityView(SecurityMode securityMode) { final LayoutInflater inflater = LayoutInflater.from(ThemeUtils.createUiContext(mContext)); if (DEBUG) Log.v(TAG, "inflating id = " + layoutId); View v = inflater.inflate(layoutId, mSecurityViewContainer, false); + if (KeyguardUpdateMonitor.sIsMultiSimEnabled) { + ViewStub vStub = (ViewStub) (v.findViewById(R.id.stub_msim_carrier_text)); + if (vStub != null) { + vStub.inflate(); + } + } mSecurityViewContainer.addView(v); updateSecurityView(v); view = (KeyguardSecurityView)v; @@ -1170,8 +1182,16 @@ private int getSecurityViewIdForMode(SecurityMode securityMode) { case Password: return R.id.keyguard_password_view; case Biometric: return R.id.keyguard_face_unlock_view; case Account: return R.id.keyguard_account_view; - case SimPin: return R.id.keyguard_sim_pin_view; - case SimPuk: return R.id.keyguard_sim_puk_view; + case SimPin: + if (KeyguardUpdateMonitor.sIsMultiSimEnabled) { + return R.id.msim_keyguard_sim_pin_view; + } + return R.id.keyguard_sim_pin_view; + case SimPuk: + if (KeyguardUpdateMonitor.sIsMultiSimEnabled) { + return R.id.msim_keyguard_sim_puk_view; + } + return R.id.keyguard_sim_puk_view; } return 0; } @@ -1184,8 +1204,16 @@ private int getLayoutIdFor(SecurityMode securityMode) { case Password: return R.layout.keyguard_password_view; case Biometric: return R.layout.keyguard_face_unlock_view; case Account: return R.layout.keyguard_account_view; - case SimPin: return R.layout.keyguard_sim_pin_view; - case SimPuk: return R.layout.keyguard_sim_puk_view; + case SimPin: + if (KeyguardUpdateMonitor.sIsMultiSimEnabled) { + return R.layout.msim_keyguard_sim_pin_view; + } + return R.layout.keyguard_sim_pin_view; + case SimPuk: + if (KeyguardUpdateMonitor.sIsMultiSimEnabled) { + return R.layout.msim_keyguard_sim_puk_view; + } + return R.layout.keyguard_sim_puk_view; default: return 0; } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java index 70909655a8341..d2582e3f07f5b 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSecurityModel.java @@ -1,6 +1,9 @@ /* * Copyright (C) 2012 The Android Open Source Project * + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * 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 @@ -19,6 +22,7 @@ import android.app.ProfileManager; import android.app.admin.DevicePolicyManager; import android.content.Context; +import android.telephony.MSimTelephonyManager; import android.telephony.TelephonyManager; import com.android.internal.telephony.IccCardConstants; @@ -81,7 +85,20 @@ private boolean isBiometricUnlockSuppressed() { SecurityMode getSecurityMode() { KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext); - final IccCardConstants.State simState = updateMonitor.getSimState(); + IccCardConstants.State simState = updateMonitor.getSimState(); + + int numPhones = MSimTelephonyManager.getDefault().getPhoneCount(); + for (int i = 0; i < numPhones; i++) { + simState = updateMonitor.getSimState(i); + // We are intereseted only in PIN_REQUIRED or PUK_REQUIRED + // So continue to the next sub if the sim state is other + // than these two. + if (simState == IccCardConstants.State.PIN_REQUIRED + || simState == IccCardConstants.State.PUK_REQUIRED) { + break; + } + } + SecurityMode mode = SecurityMode.None; if (simState == IccCardConstants.State.PIN_REQUIRED) { mode = SecurityMode.SimPin; diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java index 17a03fa4b1505..8bf54d244c9f0 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java @@ -1,6 +1,9 @@ /* * Copyright (C) 2012 The Android Open Source Project * + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * 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 @@ -43,8 +46,8 @@ public class KeyguardSimPinView extends KeyguardAbsKeyInputView implements KeyguardSecurityView, OnEditorActionListener, TextWatcher { - private ProgressDialog mSimUnlockProgressDialog = null; - private volatile boolean mSimCheckInProgress; + protected ProgressDialog mSimUnlockProgressDialog = null; + protected volatile boolean mSimCheckInProgress; public KeyguardSimPinView(Context context) { this(context, null); @@ -54,6 +57,18 @@ public KeyguardSimPinView(Context context, AttributeSet attrs) { super(context, attrs); } + protected void showCancelButton() { + final View cancel = findViewById(R.id.key_cancel); + if (cancel != null) { + cancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + doHapticKeyClick(); + } + }); + } + } + public void resetState() { String displayMessage = ""; try { @@ -91,6 +106,7 @@ public void onClick(View v) { } }); } + showCancelButton(); // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts, // not a separate view @@ -168,7 +184,7 @@ public void run() { } } - private Dialog getSimUnlockProgressDialog() { + protected Dialog getSimUnlockProgressDialog() { if (mSimUnlockProgressDialog == null) { mSimUnlockProgressDialog = new ProgressDialog(mContext); mSimUnlockProgressDialog.setMessage( diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java index 7f4ee57ad7f68..cac43f4c7b6b3 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java @@ -1,6 +1,9 @@ /* * Copyright (C) 2012 The Android Open Source Project * + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * 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 @@ -41,18 +44,18 @@ public class KeyguardSimPukView extends KeyguardAbsKeyInputView implements KeyguardSecurityView, OnEditorActionListener, TextWatcher { - private ProgressDialog mSimUnlockProgressDialog = null; - private volatile boolean mCheckInProgress; - private String mPukText; - private String mPinText; - private StateMachine mStateMachine = new StateMachine(); + protected ProgressDialog mSimUnlockProgressDialog = null; + protected volatile boolean mCheckInProgress; + protected String mPukText; + protected String mPinText; + protected StateMachine mStateMachine = new StateMachine(); - private class StateMachine { + protected class StateMachine { final int ENTER_PUK = 0; final int ENTER_PIN = 1; final int CONFIRM_PIN = 2; final int DONE = 3; - private int state = ENTER_PUK; + protected int state = ENTER_PUK; public void next() { int msg = 0; @@ -226,7 +229,7 @@ public void run() { } } - private Dialog getSimUnlockProgressDialog() { + protected Dialog getSimUnlockProgressDialog() { if (mSimUnlockProgressDialog == null) { mSimUnlockProgressDialog = new ProgressDialog(mContext); mSimUnlockProgressDialog.setMessage( @@ -241,7 +244,7 @@ private Dialog getSimUnlockProgressDialog() { return mSimUnlockProgressDialog; } - private boolean checkPuk() { + protected boolean checkPuk() { // make sure the puk is at least 8 digits long. if (mPasswordEntry.getText().length() >= 8) { mPukText = mPasswordEntry.getText().toString(); @@ -250,7 +253,7 @@ private boolean checkPuk() { return false; } - private boolean checkPin() { + protected boolean checkPin() { // make sure the PIN is between 4 and 8 digits int length = mPasswordEntry.getText().length(); if (length >= 4 && length <= 8) { @@ -264,7 +267,7 @@ public boolean confirmPin() { return mPinText.equals(mPasswordEntry.getText().toString()); } - private void updateSim() { + protected void updateSim() { getSimUnlockProgressDialog().show(); if (!mCheckInProgress) { diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java index 8c3815c1bbf0c..ff2017b2d1c2e 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java @@ -1,5 +1,7 @@ /* * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * Not a Contribution. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,8 +48,10 @@ import android.provider.Settings; import com.android.internal.telephony.IccCardConstants; +import com.android.internal.telephony.MSimConstants; import com.android.internal.telephony.TelephonyIntents; +import android.telephony.MSimTelephonyManager; import android.telephony.TelephonyManager; import android.util.Log; import com.android.internal.R; @@ -99,9 +103,9 @@ public class KeyguardUpdateMonitor { private final Context mContext; // Telephony state - private IccCardConstants.State mSimState = IccCardConstants.State.READY; - private CharSequence mTelephonyPlmn; - private CharSequence mTelephonySpn; + private IccCardConstants.State []mSimState; + private CharSequence []mTelephonyPlmn; + private CharSequence []mTelephonySpn; private int mRingMode; private int mPhoneState; private boolean mKeyguardIsVisible; @@ -127,6 +131,9 @@ public class KeyguardUpdateMonitor { private boolean mSwitchingUser; + public static final boolean + sIsMultiSimEnabled = MSimTelephonyManager.getDefault().isMultiSimEnabled(); + private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -138,7 +145,7 @@ public void handleMessage(Message msg) { handleBatteryUpdate((BatteryStatus) msg.obj); break; case MSG_CARRIER_INFO_UPDATE: - handleCarrierInfoUpdate(); + handleCarrierInfoUpdate(msg.arg1); break; case MSG_SIM_STATE_CHANGE: handleSimStateChange((SimArgs) msg.obj); @@ -248,9 +255,15 @@ public void onReceive(Context context, Intent intent) { || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) { mHandler.sendMessage(mHandler.obtainMessage(MSG_TIME_UPDATE)); } else if (TelephonyIntents.SPN_STRINGS_UPDATED_ACTION.equals(action)) { - mTelephonyPlmn = getTelephonyPlmnFrom(intent); - mTelephonySpn = getTelephonySpnFrom(intent); - mHandler.sendMessage(mHandler.obtainMessage(MSG_CARRIER_INFO_UPDATE)); + // Get the subscription from the intent. + final int subscription = intent.getIntExtra(MSimConstants.SUBSCRIPTION_KEY, 0); + Log.d(TAG, "Received SPN update on sub :" + subscription); + // Update PLMN and SPN for corresponding subscriptions. + mTelephonyPlmn[subscription] = getTelephonyPlmnFrom(intent); + mTelephonySpn[subscription] = getTelephonySpnFrom(intent); + final Message msg = mHandler.obtainMessage(MSG_CARRIER_INFO_UPDATE); + msg.arg1 = subscription; + mHandler.sendMessage(msg); } else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) { final int status = intent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN); final int plugged = intent.getIntExtra(EXTRA_PLUGGED, 0); @@ -304,16 +317,22 @@ public void onReceive(Context context, Intent intent) { */ private static class SimArgs { public final IccCardConstants.State simState; + public int subscription; - SimArgs(IccCardConstants.State state) { + SimArgs(IccCardConstants.State state, int sub) { simState = state; + subscription = sub; } static SimArgs fromIntent(Intent intent) { IccCardConstants.State state; + int subscription; if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) { throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED"); } + subscription = intent.getIntExtra(MSimConstants.SUBSCRIPTION_KEY, 0); + Log.d(TAG,"ACTION_SIM_STATE_CHANGED intent received on sub = " + subscription); + String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { final String absentReason = intent @@ -349,7 +368,7 @@ static SimArgs fromIntent(Intent intent) { } else { state = IccCardConstants.State.UNKNOWN; } - return new SimArgs(state); + return new SimArgs(state, subscription); } public String toString() { @@ -458,9 +477,19 @@ private KeyguardUpdateMonitor(Context context) { } // Take a guess at initial SIM state, battery status and PLMN until we get an update - mSimState = IccCardConstants.State.NOT_READY; mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0); - mTelephonyPlmn = getDefaultPlmn(); + // MSimTelephonyManager.getDefault().getPhoneCount() returns '1' for single SIM + // mode and '2' for dual SIM mode. + int numPhones = MSimTelephonyManager.getDefault().getPhoneCount(); + // Initialize PLMN, SPN strings and SIM states for the subscriptions. + mTelephonyPlmn = new CharSequence[numPhones]; + mTelephonySpn = new CharSequence[numPhones]; + mSimState = new IccCardConstants.State[numPhones]; + for (int i = 0; i < numPhones; i++) { + mTelephonyPlmn[i] = getDefaultPlmn(); + mTelephonySpn[i] = null; + mSimState[i] = IccCardConstants.State.NOT_READY; + } // Watch for interesting updates final IntentFilter filter = new IntentFilter(); @@ -699,14 +728,20 @@ private void handleBatteryUpdate(BatteryStatus status) { /** * Handle {@link #MSG_CARRIER_INFO_UPDATE} */ - private void handleCarrierInfoUpdate() { - if (DEBUG) Log.d(TAG, "handleCarrierInfoUpdate: plmn = " + mTelephonyPlmn - + ", spn = " + mTelephonySpn); + private void handleCarrierInfoUpdate(int subscription) { + if (DEBUG) Log.d(TAG, "handleCarrierInfoUpdate: plmn = " + mTelephonyPlmn[subscription] + + ", spn = " + mTelephonySpn[subscription] + ", subscription = " + subscription); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { - cb.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn); + if (sIsMultiSimEnabled) { + cb.onRefreshCarrierInfo(mTelephonyPlmn[subscription], + mTelephonySpn[subscription], subscription); + } else { + cb.onRefreshCarrierInfo(mTelephonyPlmn[subscription], + mTelephonySpn[subscription]); + } } } } @@ -716,18 +751,29 @@ private void handleCarrierInfoUpdate() { */ private void handleSimStateChange(SimArgs simArgs) { final IccCardConstants.State state = simArgs.simState; + final int subscription = simArgs.subscription; if (DEBUG) { Log.d(TAG, "handleSimStateChange: intentValue = " + simArgs + " " - + "state resolved to " + state.toString()); + + "state resolved to " + state.toString() + " " + + "subscription =" + subscription); } - if (state != IccCardConstants.State.UNKNOWN && state != mSimState) { - mSimState = state; + //Incase of MultiSim,unconfigured app state APPSTATE_DETECTED is reported as UNKNOWN. + //UNKNOWN state is captured to get correct number of cards configured based on state. + mSimState[subscription] = state; + if (state != IccCardConstants.State.UNKNOWN && state != mSimState[subscription]) { + if (DEBUG_SIM_STATES) Log.v(TAG, "dispatching state: " + state + + "subscription: " + subscription); + for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { - cb.onSimStateChanged(state); + if (sIsMultiSimEnabled) { + cb.onSimStateChanged(state, subscription); + } else { + cb.onSimStateChanged(state); + } } } } @@ -879,9 +925,18 @@ private void sendUpdates(KeyguardUpdateMonitorCallback callback) { callback.onTimeChanged(); callback.onRingerModeChanged(mRingMode); callback.onPhoneStateChanged(mPhoneState); - callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn); callback.onClockVisibilityChanged(); - callback.onSimStateChanged(mSimState); + int subscription = MSimTelephonyManager.getDefault().getDefaultSubscription(); + if (sIsMultiSimEnabled) { + for (int i=0; i < MSimTelephonyManager.getDefault().getPhoneCount(); i++) { + callback.onRefreshCarrierInfo(mTelephonyPlmn[i], mTelephonySpn[i], i); + callback.onSimStateChanged(mSimState[i], i); + } + } else { + callback.onRefreshCarrierInfo(mTelephonyPlmn[subscription], + mTelephonySpn[subscription]); + callback.onSimStateChanged(mSimState[subscription]); + } callback.onMusicClientIdChanged( mDisplayClientState.clientGeneration, mDisplayClientState.clearing, @@ -903,7 +958,33 @@ public void reportClockVisible(boolean visible) { } public IccCardConstants.State getSimState() { - return mSimState; + return getSimState(MSimTelephonyManager.getDefault().getDefaultSubscription()); + } + + public IccCardConstants.State getSimState(int subscription) { + return mSimState[subscription]; + } + + public int getPinLockedSubscription() { + int sub = -1; + for (int i = 0; i < mSimState.length; i++) { + if (mSimState[i] == IccCardConstants.State.PIN_REQUIRED) { + sub = i; + break; + } + } + return sub; + } + + public int getPukLockedSubscription() { + int sub = -1; + for (int i = 0; i < mSimState.length; i++) { + if (mSimState[i] == IccCardConstants.State.PUK_REQUIRED) { + sub = i; + break; + } + } + return sub; } /** @@ -915,15 +996,29 @@ public IccCardConstants.State getSimState() { * through mHandler, this *must* be called from the UI thread. */ public void reportSimUnlocked() { - handleSimStateChange(new SimArgs(IccCardConstants.State.READY)); + reportSimUnlocked(MSimTelephonyManager.getDefault().getDefaultSubscription()); + } + + public void reportSimUnlocked(int subscription) { + if (DEBUG) Log.d(TAG, "--msim--: reportSimUnlocked(" + subscription + ")"); + mSimState[subscription] = IccCardConstants.State.READY; + handleSimStateChange(new SimArgs(mSimState[subscription], subscription)); } public CharSequence getTelephonyPlmn() { - return mTelephonyPlmn; + return getTelephonyPlmn(MSimTelephonyManager.getDefault().getDefaultSubscription()); + } + + public CharSequence getTelephonyPlmn(int subscription) { + return mTelephonyPlmn[subscription]; } public CharSequence getTelephonySpn() { - return mTelephonySpn; + return getTelephonySpn(MSimTelephonyManager.getDefault().getDefaultSubscription()); + } + + public CharSequence getTelephonySpn(int subscription) { + return mTelephonySpn[subscription]; } /** @@ -972,7 +1067,18 @@ public void setAlternateUnlockEnabled(boolean enabled) { } public boolean isSimLocked() { - return isSimLocked(mSimState); + boolean isLocked = false; + for (IccCardConstants.State simState : mSimState) { + if (isSimLocked(simState)) { + isLocked = true; + break; + } + } + return isLocked; + } + + public boolean isSimLocked(int subscription) { + return isSimLocked(mSimState[subscription]); } public static boolean isSimLocked(IccCardConstants.State state) { @@ -982,7 +1088,17 @@ public static boolean isSimLocked(IccCardConstants.State state) { } public boolean isSimPinSecure() { - return isSimPinSecure(mSimState); + boolean isSecure = false; + for (IccCardConstants.State simState : mSimState) { + if (isSimPinSecure(simState)) { + isSecure = true; + break; + } + } + return isSecure; + } + public boolean isSimPinSecure(int subscription) { + return isSimPinSecure(mSimState[subscription]); } public static boolean isSimPinSecure(IccCardConstants.State state) { diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java index 41816db0edc8b..dc8ee47e10920 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java @@ -1,6 +1,9 @@ /* * Copyright (C) 2012 The Android Open Source Project * + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * 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 @@ -131,4 +134,22 @@ void onMusicClientIdChanged(int clientGeneration, boolean clearing, PendingInten */ public void onMusicPlaybackStateChanged(int playbackState, long eventTime) { } + /** + * Called when the SIM state changes on subscription. + * @param simState + * @param subscription + */ + void onSimStateChanged(IccCardConstants.State simState, int subscription) { } + + /** + * Called when the carrier PLMN or SPN changes. + * + * @param plmn The operator name of the registered network. May be null if it shouldn't + * be displayed. + * @param spn The service provider name. May be null if it shouldn't be displayed. + * @param subscription The subscription for which onRefreshCarrierInfo is meant + */ + void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn, int subscription) { } + + void initialize() { } } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java index 94dd96a3ea6ea..30f94eb28b6d7 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java @@ -1,6 +1,9 @@ /* * Copyright (C) 2007 The Android Open Source Project * + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * 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 @@ -44,6 +47,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.telephony.MSimTelephonyManager; import android.telephony.TelephonyManager; import android.util.EventLog; import android.util.Log; @@ -382,6 +386,11 @@ public void onDeviceProvisioned() { @Override public void onSimStateChanged(IccCardConstants.State simState) { + onSimStateChanged(simState, MSimTelephonyManager.getDefault().getDefaultSubscription()); + } + + @Override + public void onSimStateChanged(IccCardConstants.State simState, int subscription) { if (DEBUG) Log.d(TAG, "onSimStateChanged: " + simState); switch (simState) { @@ -916,14 +925,15 @@ private void doKeyguardLocked(Bundle options) { } // if the setup wizard hasn't run yet, don't show - final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", - false); final boolean provisioned = mUpdateMonitor.isDeviceProvisioned(); - final IccCardConstants.State state = mUpdateMonitor.getSimState(); - final boolean lockedOrMissing = state.isPinLocked() - || ((state == IccCardConstants.State.ABSENT - || state == IccCardConstants.State.PERM_DISABLED) - && requireSim); + int numPhones = MSimTelephonyManager.getDefault().getPhoneCount(); + final IccCardConstants.State []state = new IccCardConstants.State[numPhones]; + boolean lockedOrMissing = false; + for (int i = 0; i < numPhones; i++) { + state[i] = mUpdateMonitor.getSimState(i); + lockedOrMissing = lockedOrMissing || isLockedOrMissing(state[i]); + if (lockedOrMissing) break; + } if (!lockedOrMissing && !provisioned) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned" @@ -941,6 +951,15 @@ private void doKeyguardLocked(Bundle options) { showLocked(options); } + boolean isLockedOrMissing(IccCardConstants.State state) { + final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", + false); + return (state.isPinLocked() + || ((state == IccCardConstants.State.ABSENT + || state == IccCardConstants.State.PERM_DISABLED) + && requireSim)); + } + /** * Dismiss the keyguard through the security layers. */ diff --git a/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimCarrierText.java b/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimCarrierText.java new file mode 100644 index 0000000000000..4ef75e030c263 --- /dev/null +++ b/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimCarrierText.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.policy.impl.keyguard; + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.widget.TextView; + +import android.util.Log; + +import com.android.internal.R; +import com.android.internal.telephony.IccCardConstants; +import com.android.internal.telephony.IccCardConstants.State; +import com.android.internal.widget.LockPatternUtils; + +import android.telephony.MSimTelephonyManager; + +public class MSimCarrierText extends CarrierText { + private static final String TAG = "MSimCarrierText"; + + private KeyguardUpdateMonitorCallback mMSimCallback = new KeyguardUpdateMonitorCallback() { + private CharSequence []mPlmn; + private CharSequence []mSpn; + private State []mSimState; + + @Override + public void initialize() { + int numPhones = MSimTelephonyManager.getDefault().getPhoneCount(); + mPlmn = new CharSequence[numPhones]; + mSpn = new CharSequence[numPhones]; + mSimState = new State[numPhones]; + } + + @Override + public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn, int sub) { + mPlmn[sub] = plmn; + mSpn[sub] = spn; + updateCarrierText(mSimState, mPlmn, mSpn); + } + + @Override + public void onSimStateChanged(IccCardConstants.State simState, int sub) { + mSimState[sub] = simState; + updateCarrierText(mSimState, mPlmn, mSpn); + } + }; + + public MSimCarrierText(Context context) { + this(context, null); + } + + public MSimCarrierText(Context context, AttributeSet attrs) { + super(context, attrs); + mMSimCallback.initialize(); + } + + protected void updateCarrierText(State []simState, CharSequence []plmn, CharSequence []spn) { + CharSequence text = ""; + for (int i = 0; i < simState.length; i++) { + CharSequence displayText = getCarrierTextForSimState(simState[i], plmn[i], spn[i]); + if (KeyguardViewManager.USE_UPPER_CASE) { + displayText = (displayText != null ? displayText.toString().toUpperCase() : ""); + } + text = (TextUtils.isEmpty(text) + ? displayText + : getContext().getString(R.string.msim_carrier_text_format, text, displayText)); + } + Log.d(TAG, "updateCarrierText: text = " + text); + setText(text); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mMSimCallback); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mMSimCallback); + } +} + diff --git a/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPinView.java b/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPinView.java new file mode 100644 index 0000000000000..1fb44e8b59185 --- /dev/null +++ b/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPinView.java @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.policy.impl.keyguard; + +import com.android.internal.telephony.msim.ITelephonyMSim; + +import android.content.Context; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.telephony.MSimTelephonyManager; +import android.util.AttributeSet; +import android.view.View; +import android.util.Log; + +import com.android.internal.R; +import com.android.internal.telephony.IccCardConstants; + +/** + * Displays a PIN pad for unlocking. + */ +public class MSimKeyguardSimPinView extends KeyguardSimPinView { + private final static boolean DEBUG = KeyguardViewMediator.DEBUG; + private static String TAG = "MSimKeyguardSimPinView"; + private static int sCancelledCount = 0; + + public MSimKeyguardSimPinView(Context context) { + this(context, null); + } + + public MSimKeyguardSimPinView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void showCancelButton() { + final View cancel = findViewById(R.id.key_cancel); + if (cancel != null) { + cancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + doHapticKeyClick(); + MSimKeyguardSimPinView.sCancelledCount++; + closeKeyGuard(false); + } + }); + } + } + + private void closeKeyGuard(boolean bAuthenticated) { + KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(getContext()); + int numCardsPresent = 0; + int numPinLocked = 0; + IccCardConstants.State simState = IccCardConstants.State.UNKNOWN; + + int numPhones = MSimTelephonyManager.getDefault().getPhoneCount(); + for (int i = 0; i < numPhones; i++) { + simState = updateMonitor.getSimState(i); + if (simState.isPinLocked()) { + numPinLocked++; + } + + if (simState.iccCardExist()) { + numCardsPresent++; + } + } + //If Cancel is pressed for last sub, don't allow cancel and decrement Count. + if (!bAuthenticated && MSimKeyguardSimPinView.sCancelledCount >= numCardsPresent) { + MSimKeyguardSimPinView.sCancelledCount--; + return; + } + + //If this is last PIN lock screen, we will show HomeScreen now. + //Hence reset the static sCancelledCount variable. + if (numPinLocked <= 1) { + MSimKeyguardSimPinView.sCancelledCount = 0; + } + + updateMonitor.reportSimUnlocked(updateMonitor.getPinLockedSubscription()); + mCallback.dismiss(true); + } + + public void resetState() { + mSecurityMessageDisplay.setMessage( + getSecurityMessageDisplay(R.string.kg_sim_pin_instructions), true); + mPasswordEntry.setEnabled(true); + } + + /** + * Since the IPC can block, we want to run the request in a separate thread + * with a callback. + */ + private abstract class MSimCheckSimPin extends Thread { + private final String mPin; + protected final int mSubscription; + + protected MSimCheckSimPin(String pin, int sub) { + mPin = pin; + mSubscription = sub; + } + + abstract void onSimCheckResponse(boolean success); + + @Override + public void run() { + try { + if (DEBUG) Log.d(TAG, "MSimCheckSimPin:run(), mPin = " + mPin + + " mSubscription = " + mSubscription); + final boolean result = ITelephonyMSim.Stub.asInterface(ServiceManager + .checkService("phone_msim")).supplyPin(mPin, mSubscription); + post(new Runnable() { + public void run() { + onSimCheckResponse(result); + } + }); + } catch (RemoteException e) { + post(new Runnable() { + public void run() { + onSimCheckResponse(false); + } + }); + } + } + } + + @Override + protected void verifyPasswordAndUnlock() { + String entry = mPasswordEntry.getText().toString(); + if (DEBUG) Log.d(TAG, "verifyPasswordAndUnlock(): entry = " + entry); + + if (entry.length() < 4) { + // otherwise, display a message to the user, and don't submit. + mSecurityMessageDisplay.setMessage( + getSecurityMessageDisplay(R.string.kg_invalid_sim_pin_hint), true); + mPasswordEntry.setText(""); + mCallback.userActivity(0); + return; + } + + getSimUnlockProgressDialog().show(); + + if (!mSimCheckInProgress) { + mSimCheckInProgress = true; // there should be only one + + if (DEBUG) Log.d(TAG, "startCheckSimPin(), Multi SIM enabled"); + new MSimCheckSimPin(mPasswordEntry.getText().toString(), + KeyguardUpdateMonitor.getInstance(mContext).getPinLockedSubscription()) { + void onSimCheckResponse(final boolean success) { + post(new Runnable() { + public void run() { + if (mSimUnlockProgressDialog != null) { + mSimUnlockProgressDialog.hide(); + } + if (success) { + // before closing the keyguard, report back that the sim is unlocked + // so it knows right away. + closeKeyGuard(success); + } else { + mSecurityMessageDisplay.setMessage(getSecurityMessageDisplay + (R.string.kg_password_wrong_pin_code), true); + mPasswordEntry.setText(""); + } + mCallback.userActivity(0); + mSimCheckInProgress = false; + } + }); + } + }.start(); + } + } + + protected CharSequence getSecurityMessageDisplay(int resId) { + // Returns the String in the format + // "SUB:%d : %s", sub, msg + return getContext().getString(R.string.msim_kg_sim_pin_msg_format, + KeyguardUpdateMonitor.getInstance(mContext).getPinLockedSubscription()+1, + getContext().getResources().getText(resId)); + } +} + diff --git a/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPukView.java b/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPukView.java new file mode 100755 index 0000000000000..a11cdf5b6524e --- /dev/null +++ b/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPukView.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.internal.policy.impl.keyguard; + +import android.content.Context; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.AttributeSet; +import android.util.Log; + +import com.android.internal.telephony.msim.ITelephonyMSim; + +import com.android.internal.R; + +/** + * Displays a PIN pad for entering a PUK (Pin Unlock Kode) provided by a carrier. + */ +public class MSimKeyguardSimPukView extends KeyguardSimPukView { + private final static boolean DEBUG = KeyguardViewMediator.DEBUG; + private static String TAG = "MSimKeyguardSimPukView"; + + protected class MSimStateMachine extends KeyguardSimPukView.StateMachine { + public void next() { + int msg = 0; + if (state == ENTER_PUK) { + if (checkPuk()) { + state = ENTER_PIN; + msg = R.string.kg_puk_enter_pin_hint; + } else { + msg = R.string.kg_invalid_sim_puk_hint; + } + } else if (state == ENTER_PIN) { + if (checkPin()) { + state = CONFIRM_PIN; + msg = R.string.kg_enter_confirm_pin_hint; + } else { + msg = R.string.kg_invalid_sim_pin_hint; + } + } else if (state == CONFIRM_PIN) { + if (confirmPin()) { + state = DONE; + msg = + com.android.internal.R.string.lockscreen_sim_unlock_progress_dialog_message; + updateSim(); + } else { + state = ENTER_PIN; // try again? + msg = R.string.kg_invalid_confirm_pin_hint; + } + } + mPasswordEntry.setText(null); + if (msg != 0) { + mSecurityMessageDisplay.setMessage(getSecurityMessageDisplay(msg), true); + } + } + + void reset() { + mPinText=""; + mPukText=""; + state = ENTER_PUK; + mSecurityMessageDisplay.setMessage( + getSecurityMessageDisplay(R.string.kg_puk_enter_puk_hint), true); + mPasswordEntry.requestFocus(); + } + } + + public MSimKeyguardSimPukView(Context context) { + this(context, null); + } + + public MSimKeyguardSimPukView(Context context, AttributeSet attrs) { + super(context, attrs); + mStateMachine = new MSimStateMachine(); + } + + /** + * Since the IPC can block, we want to run the request in a separate thread + * with a callback. + */ + private abstract class MSimCheckSimPuk extends Thread { + private final String mPin, mPuk; + protected final int mSubscription; + + protected MSimCheckSimPuk(String puk, String pin, int sub) { + mPuk = puk; + mPin = pin; + mSubscription = sub; + } + + abstract void onSimLockChangedResponse(boolean success); + + @Override + public void run() { + if (DEBUG) Log.d(TAG, "MSimCheckSimPuk:run(), mPuk = " + mPuk + + " mPin = " + mPin + " mSubscription = " + mSubscription); + try { + final boolean result = ITelephonyMSim.Stub.asInterface(ServiceManager + .checkService("phone_msim")).supplyPuk(mPuk, mPin, mSubscription); + + post(new Runnable() { + public void run() { + onSimLockChangedResponse(result); + } + }); + } catch (RemoteException e) { + post(new Runnable() { + public void run() { + onSimLockChangedResponse(false); + } + }); + } + } + } + + @Override + protected void updateSim() { + getSimUnlockProgressDialog().show(); + + if (DEBUG) Log.d(TAG, "updateSim()"); + + if (!mCheckInProgress) { + mCheckInProgress = true; + + new MSimCheckSimPuk(mPukText, mPinText, + KeyguardUpdateMonitor.getInstance(mContext).getPukLockedSubscription()) { + void onSimLockChangedResponse(final boolean success) { + post(new Runnable() { + public void run() { + if (mSimUnlockProgressDialog != null) { + mSimUnlockProgressDialog.hide(); + } + if (success) { + mCallback.dismiss(true); + } else { + mStateMachine.reset(); + mSecurityMessageDisplay.setMessage( + getSecurityMessageDisplay(R.string.kg_invalid_puk), true); + } + mCheckInProgress = false; + } + }); + } + }.start(); + } + } + + protected CharSequence getSecurityMessageDisplay(int resId) { + // Returns the String in the format + // "SUB:%d : %s", sub, msg + return getContext().getString(R.string.msim_kg_sim_pin_msg_format, + KeyguardUpdateMonitor.getInstance(mContext).getPukLockedSubscription()+1, + getContext().getResources().getText(resId)); + } +} + From d6da6fa0a70a935859c965903161e6ff5da76a61 Mon Sep 17 00:00:00 2001 From: Rakesh Pallerla Date: Tue, 26 Mar 2013 16:16:19 +0530 Subject: [PATCH 056/204] Telephony: Added ME Depersonalization support. Added support for all ME De-Personalizations as per specs 3GPP2 C.S0068-0 and 3GPP TS 22.022. CRs-fixed: 467276 Change-Id: Iba74e3e5eb4fe96361585f4933897c5c8f17db97 --- core/res/res/values/strings.xml | 2 ++ core/res/res/values/symbols.xml | 1 + .../statusbar/phone/PhoneStatusBarPolicy.java | 2 +- .../statusbar/policy/MSimNetworkController.java | 2 +- .../statusbar/policy/NetworkController.java | 2 +- .../policy/impl/keyguard/CarrierText.java | 17 +++++++++-------- .../impl/keyguard/KeyguardUpdateMonitor.java | 4 ++-- .../android/telephony/TelephonyManager.java | 2 +- .../internal/telephony/IccCardConstants.java | 8 ++++---- .../internal/telephony/RILConstants.java | 2 +- .../internal/telephony/TelephonyProperties.java | 2 +- 11 files changed, 24 insertions(+), 20 deletions(-) diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index a07123190853e..39d9b1257ec9d 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -2236,6 +2236,8 @@ locked --> Network locked + + SIM/RUIM is Perso locked diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 042fb1fe3b2bd..00df1578d75c5 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1469,6 +1469,7 @@ + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java index f4fdec343eeef..34e8817e51fb0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -242,7 +242,7 @@ else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { simState = IccCardConstants.State.PUK_REQUIRED; } else { - simState = IccCardConstants.State.NETWORK_LOCKED; + simState = IccCardConstants.State.PERSO_LOCKED; } } else { simState = IccCardConstants.State.UNKNOWN; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java index d10f297c1e252..470ece5693583 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java @@ -420,7 +420,7 @@ else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { simState = IccCardConstants.State.PUK_REQUIRED; } else { - simState = IccCardConstants.State.NETWORK_LOCKED; + simState = IccCardConstants.State.PERSO_LOCKED; } } else { simState = IccCardConstants.State.UNKNOWN; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 3627456519a8d..95ab841c054dd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -553,7 +553,7 @@ else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { mSimState = IccCardConstants.State.PUK_REQUIRED; } else { - mSimState = IccCardConstants.State.NETWORK_LOCKED; + mSimState = IccCardConstants.State.PERSO_LOCKED; } } else { mSimState = IccCardConstants.State.UNKNOWN; diff --git a/policy/src/com/android/internal/policy/impl/keyguard/CarrierText.java b/policy/src/com/android/internal/policy/impl/keyguard/CarrierText.java index ab2c2edc92c2e..5c7675ec1117a 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/CarrierText.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/CarrierText.java @@ -57,7 +57,7 @@ public void onSimStateChanged(IccCardConstants.State simState) { */ private static enum StatusMode { Normal, // Normal case (sim card present, it's not locked) - NetworkLocked, // SIM card is 'network locked'. + PersoLocked, // SIM card is 'perso locked'. SimMissing, // SIM card is missing. SimMissingLocked, // SIM card is missing, and device isn't provisioned; don't allow access SimPukLocked, // SIM card is PUK locked because SIM entered wrong too many times @@ -129,9 +129,10 @@ protected CharSequence getCarrierTextForSimState(IccCardConstants.State simState carrierText = null; // nothing to display yet. break; - case NetworkLocked: + case PersoLocked: carrierText = makeCarrierStringOnEmergencyCapable( - mContext.getText(R.string.lockscreen_network_locked_message), plmn); + getContext().getText(R.string.lockscreen_perso_locked_message), + plmn); break; case SimMissing: @@ -202,13 +203,13 @@ private StatusMode getStatusForIccState(IccCardConstants.State simState) { && (simState == IccCardConstants.State.ABSENT || simState == IccCardConstants.State.PERM_DISABLED); - // Assume we're NETWORK_LOCKED if not provisioned - simState = missingAndNotProvisioned ? IccCardConstants.State.NETWORK_LOCKED : simState; + // Assume we're PERSO_LOCKED if not provisioned + simState = missingAndNotProvisioned ? IccCardConstants.State.PERSO_LOCKED : simState; switch (simState) { case ABSENT: return StatusMode.SimMissing; - case NETWORK_LOCKED: - return StatusMode.SimMissingLocked; + case PERSO_LOCKED: + return StatusMode.PersoLocked; case NOT_READY: return StatusMode.SimNotReady; case PIN_REQUIRED: @@ -246,7 +247,7 @@ private CharSequence getCarrierHelpTextForSimState(IccCardConstants.State simSta int carrierHelpTextId = 0; StatusMode status = getStatusForIccState(simState); switch (status) { - case NetworkLocked: + case PersoLocked: carrierHelpTextId = R.string.lockscreen_instructions_when_pattern_disabled; break; diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java index ff2017b2d1c2e..27b25e751b63c 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java @@ -353,13 +353,13 @@ static SimArgs fromIntent(Intent intent) { state = IccCardConstants.State.PIN_REQUIRED; } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { state = IccCardConstants.State.PUK_REQUIRED; + } else if (IccCardConstants.INTENT_VALUE_LOCKED_PERSO.equals(lockedReason)) { + state = IccCardConstants.State.PERSO_LOCKED; } else { state = IccCardConstants.State.UNKNOWN; } } else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) { state = IccCardConstants.State.CARD_IO_ERROR; - } else if (IccCardConstants.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) { - state = IccCardConstants.State.NETWORK_LOCKED; } else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra) || IccCardConstants.INTENT_VALUE_ICC_IMSI.equals(stateExtra)) { // This is required because telephony doesn't return to "READY" after diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 6f8ee227541ff..a1c23d00def13 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -897,7 +897,7 @@ else if ("PIN_REQUIRED".equals(prop)) { else if ("PUK_REQUIRED".equals(prop)) { return SIM_STATE_PUK_REQUIRED; } - else if ("NETWORK_LOCKED".equals(prop)) { + else if ("PERSO_LOCKED".equals(prop)) { return SIM_STATE_NETWORK_LOCKED; } else if ("READY".equals(prop)) { diff --git a/telephony/java/com/android/internal/telephony/IccCardConstants.java b/telephony/java/com/android/internal/telephony/IccCardConstants.java index 80297132ab7be..6dd91e98cbfb1 100644 --- a/telephony/java/com/android/internal/telephony/IccCardConstants.java +++ b/telephony/java/com/android/internal/telephony/IccCardConstants.java @@ -44,8 +44,8 @@ public class IccCardConstants { public static final String INTENT_VALUE_LOCKED_ON_PIN = "PIN"; /* PUK means ICC is locked on PUK1 */ public static final String INTENT_VALUE_LOCKED_ON_PUK = "PUK"; - /* NETWORK means ICC is locked on NETWORK PERSONALIZATION */ - public static final String INTENT_VALUE_LOCKED_NETWORK = "NETWORK"; + /* PERSO means ICC is locked on PERSONALIZATION */ + public static final String INTENT_VALUE_LOCKED_PERSO = "PERSO"; /* PERM_DISABLED means ICC is permanently disabled due to puk fails */ public static final String INTENT_VALUE_ABSENT_ON_PERM_DISABLED = "PERM_DISABLED"; @@ -62,7 +62,7 @@ public enum State { ABSENT, PIN_REQUIRED, PUK_REQUIRED, - NETWORK_LOCKED, + PERSO_LOCKED, READY, NOT_READY, PERM_DISABLED, @@ -74,7 +74,7 @@ public boolean isPinLocked() { public boolean iccCardExist() { return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED) - || (this == NETWORK_LOCKED) || (this == READY) + || (this == PERSO_LOCKED) || (this == READY) || (this == PERM_DISABLED) || (this == CARD_IO_ERROR)); } } diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index d40acf9415e99..cd453aa38f0ba 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -190,7 +190,7 @@ class C */ int RIL_REQUEST_ENTER_SIM_PUK2 = 5; int RIL_REQUEST_CHANGE_SIM_PIN = 6; int RIL_REQUEST_CHANGE_SIM_PIN2 = 7; - int RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION = 8; + int RIL_REQUEST_ENTER_DEPERSONALIZATION_CODE = 8; int RIL_REQUEST_GET_CURRENT_CALLS = 9; int RIL_REQUEST_DIAL = 10; int RIL_REQUEST_GET_IMSI = 11; diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index 793fc13b7eb86..b08238e2e41bc 100755 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -101,7 +101,7 @@ public interface TelephonyProperties //****** SIM Card /** * One of "UNKNOWN" "ABSENT" "PIN_REQUIRED" - * "PUK_REQUIRED" "NETWORK_LOCKED" or "READY" + * "PUK_REQUIRED" "PERSO_LOCKED" or "READY" */ static String PROPERTY_SIM_STATE = "gsm.sim.state"; From bcf3b86394e6311ad44a294e4a5a576c398f5be1 Mon Sep 17 00:00:00 2001 From: Rakesh Pallerla Date: Mon, 8 Jul 2013 18:49:16 +0530 Subject: [PATCH 057/204] Telephony: Add DETECTED state and PIN/PUK retry count. 1. Add App state DETECTED in the IccCardConstants.State enum. Modified logic for allowing PIN cancel based on number of cards configured/activated instead of number of cards present. 2. Add method in ITelephonyMSim.aidl to retrieve PIN1RetryCount. Display Attempts remaining in PIN/PUK lockscreen UI. 3. Clean up KeyguardUpdateMonitorCallback and MSimCarrierText by removing Initialize method from Callback. Change-Id: I89c9825b35257c1cca5946bf0cbffedb07d0015b CRs-Fixed: 501887, 504086, 508283, 510400, 513293 --- .../impl/keyguard/KeyguardUpdateMonitor.java | 14 ++-- .../KeyguardUpdateMonitorCallback.java | 2 - .../impl/keyguard/msim/MSimCarrierText.java | 23 +++--- .../keyguard/msim/MSimKeyguardSimPinView.java | 77 +++++++++++++++---- .../keyguard/msim/MSimKeyguardSimPukView.java | 20 ++++- .../internal/telephony/IccCardConstants.java | 6 +- .../telephony/msim/ITelephonyMSim.aidl | 6 ++ 7 files changed, 108 insertions(+), 40 deletions(-) mode change 100755 => 100644 policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPukView.java diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java index 27b25e751b63c..33f1717f191f9 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitor.java @@ -753,19 +753,15 @@ private void handleSimStateChange(SimArgs simArgs) { final IccCardConstants.State state = simArgs.simState; final int subscription = simArgs.subscription; - if (DEBUG) { - Log.d(TAG, "handleSimStateChange: intentValue = " + simArgs + " " - + "state resolved to " + state.toString() + " " - + "subscription =" + subscription); - } + Log.d(TAG, "handleSimStateChange: intentValue = " + simArgs + " " + + "state resolved to " + state.toString() + " " + + "subscription =" + subscription); - //Incase of MultiSim,unconfigured app state APPSTATE_DETECTED is reported as UNKNOWN. - //UNKNOWN state is captured to get correct number of cards configured based on state. - mSimState[subscription] = state; if (state != IccCardConstants.State.UNKNOWN && state != mSimState[subscription]) { if (DEBUG_SIM_STATES) Log.v(TAG, "dispatching state: " + state + "subscription: " + subscription); + mSimState[subscription] = state; for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -1000,7 +996,7 @@ public void reportSimUnlocked() { } public void reportSimUnlocked(int subscription) { - if (DEBUG) Log.d(TAG, "--msim--: reportSimUnlocked(" + subscription + ")"); + if (DEBUG) Log.d(TAG, "reportSimUnlocked(" + subscription + ")"); mSimState[subscription] = IccCardConstants.State.READY; handleSimStateChange(new SimArgs(mSimState[subscription], subscription)); } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java index dc8ee47e10920..7eadf531fea84 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardUpdateMonitorCallback.java @@ -150,6 +150,4 @@ void onSimStateChanged(IccCardConstants.State simState, int subscription) { } * @param subscription The subscription for which onRefreshCarrierInfo is meant */ void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn, int subscription) { } - - void initialize() { } } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimCarrierText.java b/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimCarrierText.java index 4ef75e030c263..212a34b8b51de 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimCarrierText.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimCarrierText.java @@ -34,19 +34,11 @@ public class MSimCarrierText extends CarrierText { private static final String TAG = "MSimCarrierText"; + private CharSequence []mPlmn; + private CharSequence []mSpn; + private State []mSimState; private KeyguardUpdateMonitorCallback mMSimCallback = new KeyguardUpdateMonitorCallback() { - private CharSequence []mPlmn; - private CharSequence []mSpn; - private State []mSimState; - - @Override - public void initialize() { - int numPhones = MSimTelephonyManager.getDefault().getPhoneCount(); - mPlmn = new CharSequence[numPhones]; - mSpn = new CharSequence[numPhones]; - mSimState = new State[numPhones]; - } @Override public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn, int sub) { @@ -62,13 +54,20 @@ public void onSimStateChanged(IccCardConstants.State simState, int sub) { } }; + private void initialize() { + int numPhones = MSimTelephonyManager.getDefault().getPhoneCount(); + mPlmn = new CharSequence[numPhones]; + mSpn = new CharSequence[numPhones]; + mSimState = new State[numPhones]; + } + public MSimCarrierText(Context context) { this(context, null); } public MSimCarrierText(Context context, AttributeSet attrs) { super(context, attrs); - mMSimCallback.initialize(); + initialize(); } protected void updateCarrierText(State []simState, CharSequence []plmn, CharSequence []spn) { diff --git a/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPinView.java b/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPinView.java index 1fb44e8b59185..d20d2b2e3c9f9 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPinView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPinView.java @@ -38,6 +38,7 @@ public class MSimKeyguardSimPinView extends KeyguardSimPinView { private final static boolean DEBUG = KeyguardViewMediator.DEBUG; private static String TAG = "MSimKeyguardSimPinView"; private static int sCancelledCount = 0; + private int mSubscription = -1; public MSimKeyguardSimPinView(Context context) { this(context, null); @@ -55,34 +56,63 @@ protected void showCancelButton() { @Override public void onClick(View v) { doHapticKeyClick(); - MSimKeyguardSimPinView.sCancelledCount++; closeKeyGuard(false); } }); } } + /* + * CloseKeyGuard: Method used to Close the keyguard. + * @param bAuthenticated: + * true: user entered correct PIN and pressed OK. + * false: user pressed cancel. + * + * Description: used to close keyguard when user presses cancel or + * user enters correct PIN and presses OK + * + * Logic: + * 1. Calculate number of SIMs configured i.e. selected from MultiSIM settings + * 2. Calculate number of SIMs which are PIN Locked + * 3. sCancelledCount will tell us number of keyguards got cancelled. If user tries to cancel + * all Keyguard screens, do not allow him to close Keyguard as atleast one SIM has to + * be authenticated before allowing user to access HomeScreen. + * 4. If present keyguard screen is last one we are about to show HomeScreen after closing this + * keyguard so reset the sCancelledCount. + * 5. Report SIM unlocked to KGUpdateMonitor so that keyguard is closed right away without + * waiting for indication from framework. + */ private void closeKeyGuard(boolean bAuthenticated) { KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(getContext()); - int numCardsPresent = 0; + int numCardsConfigured = 0; int numPinLocked = 0; IccCardConstants.State simState = IccCardConstants.State.UNKNOWN; int numPhones = MSimTelephonyManager.getDefault().getPhoneCount(); for (int i = 0; i < numPhones; i++) { simState = updateMonitor.getSimState(i); - if (simState.isPinLocked()) { + if (simState == IccCardConstants.State.PIN_REQUIRED) { numPinLocked++; } - if (simState.iccCardExist()) { - numCardsPresent++; + //Get number of cards that are present and configured. + //Exclude cards with DETECTED state as they are not configured and are not used. + if (simState == IccCardConstants.State.READY || + simState == IccCardConstants.State.PIN_REQUIRED || + simState == IccCardConstants.State.PUK_REQUIRED || + simState == IccCardConstants.State.PERSO_LOCKED) { + numCardsConfigured++; } } - //If Cancel is pressed for last sub, don't allow cancel and decrement Count. - if (!bAuthenticated && MSimKeyguardSimPinView.sCancelledCount >= numCardsPresent) { - MSimKeyguardSimPinView.sCancelledCount--; - return; + + //If Cancel is pressed for last configured sub return without incrementing sCancelledCount + // else increment sCancelledCount. + if (!bAuthenticated) { + if (MSimKeyguardSimPinView.sCancelledCount >= (numCardsConfigured - 1)) { + return; + } else { + MSimKeyguardSimPinView.sCancelledCount++; + } } //If this is last PIN lock screen, we will show HomeScreen now. @@ -91,13 +121,35 @@ private void closeKeyGuard(boolean bAuthenticated) { MSimKeyguardSimPinView.sCancelledCount = 0; } - updateMonitor.reportSimUnlocked(updateMonitor.getPinLockedSubscription()); + //If Cancel is pressed get current locked sub, + //In case user presses OK we anyways have locked sub, no need to get again. + if (!bAuthenticated) mSubscription = updateMonitor.getPinLockedSubscription(); + + //Before closing the keyguard, report back that the sim is unlocked + //so it knows right away. + if (mSubscription >= 0) updateMonitor.reportSimUnlocked(mSubscription); mCallback.dismiss(true); } public void resetState() { - mSecurityMessageDisplay.setMessage( - getSecurityMessageDisplay(R.string.kg_sim_pin_instructions), true); + String displayMessage = ""; + try { + mSubscription = KeyguardUpdateMonitor.getInstance(mContext) + .getPinLockedSubscription(); + int attemptsRemaining = ITelephonyMSim.Stub.asInterface(ServiceManager + .checkService("phone_msim")).getIccPin1RetryCount(mSubscription); + + if (attemptsRemaining >= 0) { + displayMessage = getContext().getString(R.string.keyguard_password_wrong_pin_code) + + getContext().getString(R.string.pinpuk_attempts) + + attemptsRemaining + ". "; + } + } catch (RemoteException ex) { + displayMessage = getContext().getString(R.string.keyguard_password_pin_failed); + } + displayMessage = getSecurityMessageDisplay(R.string.kg_sim_pin_instructions) + + displayMessage; + mSecurityMessageDisplay.setMessage(displayMessage, true); mPasswordEntry.setEnabled(true); } @@ -107,7 +159,6 @@ public void resetState() { */ private abstract class MSimCheckSimPin extends Thread { private final String mPin; - protected final int mSubscription; protected MSimCheckSimPin(String pin, int sub) { mPin = pin; diff --git a/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPukView.java b/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPukView.java old mode 100755 new mode 100644 index a11cdf5b6524e..82712ab475e6d --- a/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPukView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/msim/MSimKeyguardSimPukView.java @@ -69,11 +69,27 @@ public void next() { } void reset() { + String displayMessage = ""; + try { + int attemptsRemaining = ITelephonyMSim.Stub.asInterface(ServiceManager + .checkService("phone_msim")).getIccPin1RetryCount(KeyguardUpdateMonitor + .getInstance(mContext).getPukLockedSubscription()); + if (attemptsRemaining >= 0) { + displayMessage = getContext().getString( + R.string.keyguard_password_wrong_puk_code) + + getContext().getString(R.string.pinpuk_attempts) + + attemptsRemaining + ". "; + } + } catch (RemoteException ex) { + displayMessage = getContext().getString( + R.string.keyguard_password_puk_failed); + } + displayMessage = getSecurityMessageDisplay(R.string.kg_puk_enter_puk_hint) + + displayMessage; mPinText=""; mPukText=""; state = ENTER_PUK; - mSecurityMessageDisplay.setMessage( - getSecurityMessageDisplay(R.string.kg_puk_enter_puk_hint), true); + mSecurityMessageDisplay.setMessage(displayMessage, true); mPasswordEntry.requestFocus(); } } diff --git a/telephony/java/com/android/internal/telephony/IccCardConstants.java b/telephony/java/com/android/internal/telephony/IccCardConstants.java index 6dd91e98cbfb1..29b2f193c2d8f 100644 --- a/telephony/java/com/android/internal/telephony/IccCardConstants.java +++ b/telephony/java/com/android/internal/telephony/IccCardConstants.java @@ -66,7 +66,8 @@ public enum State { READY, NOT_READY, PERM_DISABLED, - CARD_IO_ERROR; + CARD_IO_ERROR, + DETECTED; public boolean isPinLocked() { return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED)); @@ -75,7 +76,8 @@ public boolean isPinLocked() { public boolean iccCardExist() { return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED) || (this == PERSO_LOCKED) || (this == READY) - || (this == PERM_DISABLED) || (this == CARD_IO_ERROR)); + || (this == PERM_DISABLED) || (this == CARD_IO_ERROR) + || (this == DETECTED)); } } } diff --git a/telephony/java/com/android/internal/telephony/msim/ITelephonyMSim.aidl b/telephony/java/com/android/internal/telephony/msim/ITelephonyMSim.aidl index a6add360ee44d..763c44a6eb7b9 100644 --- a/telephony/java/com/android/internal/telephony/msim/ITelephonyMSim.aidl +++ b/telephony/java/com/android/internal/telephony/msim/ITelephonyMSim.aidl @@ -174,6 +174,12 @@ interface ITelephonyMSim { */ boolean supplyPuk(String puk, String pin, int subscription); + /** + * Gets the number of attempts remaining for PIN1/PUK1 unlock. + * @param subscription for which attempts remaining is required. + */ + int getIccPin1RetryCount(int subscription); + /** * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated * without SEND (so dial is not appropriate) for From 44619791fe6be551c7cd053c79cbde4f8aaff515 Mon Sep 17 00:00:00 2001 From: Chaitanya Saggurthi Date: Thu, 18 Jul 2013 12:03:14 +0530 Subject: [PATCH 058/204] Telephony: Remove CDMA cellbroadcast API's Remove CDMA cellbroadcast API's, handle CDMA cellbroadcast management based on phone type in IccSmsInterfaceManager to sync with AOSP. Change-Id: I25b382d232799e964e8812de99c46e2dd372b20f --- .../com/android/internal/telephony/ISms.aidl | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl index 4e4136ffdbf33..a94bcc9728e19 100644 --- a/telephony/java/com/android/internal/telephony/ISms.aidl +++ b/telephony/java/com/android/internal/telephony/ISms.aidl @@ -203,31 +203,6 @@ interface ISms { */ boolean disableCellBroadcast(int messageIdentifier); - /** - * Enable reception of cdma broadcast messages with the given - * message identifier. Note that if two different clients enable the same - * message identifier, they must both disable it for the device to stop - * receiving those messages. - * - * @param messageIdentifier Message identifier as specified in C.R1001-G - * @return true if successful, false otherwise - * @see #disableCdmaBroadcast(int) - */ - boolean enableCdmaBroadcast(int messageIdentifier); - - /** - * Disable reception of cdma broadcast messages with the given - * message identifier. Note that if two different clients enable the same - * message identifier, they must both disable it for the device to stop - * receiving those messages. - * - * @param messageIdentifier Message identifier as specified in C.R1001-G - * @return true if successful, false otherwise - * - * @see #enableCdmaBroadcast(int) - */ - boolean disableCdmaBroadcast(int messageIdentifier); - /* * Enable reception of cell broadcast (SMS-CB) messages with the given * message identifier range. Note that if two different clients enable @@ -260,34 +235,6 @@ interface ISms { */ boolean disableCellBroadcastRange(int startMessageId, int endMessageId); - /** - * Enable reception of cdma broadcast messages with the given - * message identifier range. Note that if two different clients enable - * a message identifier range, they must both disable it for the device - * to stop receiving those messages. - * - * @param startMessageId first message identifier as specified in C.R1001-G - * @param endMessageId last message identifier as specified in C.R1001-G - * @return true if successful, false otherwise - * - * @see #disableCdmaBroadcastRange(int, int) - */ - boolean enableCdmaBroadcastRange(int startMessageId, int endMessageId); - - /** - * Disable reception of cdma broadcast messages with the given - * message identifier range. Note that if two different clients enable - * a message identifier range, they must both disable it for the device - * to stop receiving those messages. - * - * @param startMessageId first message identifier as specified in C.R1001-G - * @param endMessageId last message identifier as specified in C.R1001-G - * @return true if successful, false otherwise - * - * @see #enableCdmaBroadcastRange(int, int) - */ - boolean disableCdmaBroadcastRange(int startMessageId, int endMessageId); - /** * Returns the premium SMS send permission for the specified package. * Requires system permission. From 7c514bc96b3227577ec829072f7bc74da02e5ebb Mon Sep 17 00:00:00 2001 From: Garik Badalyan Date: Mon, 15 Jul 2013 11:27:25 -0700 Subject: [PATCH 059/204] CSVT: Introduce Circuit-Switch Video Telephony. Introduce CSVT Service which provides necessary API for Circuit-Switch Video Telephony. Change-Id: I1d483212450720d64d05f4e2b02abf8da9f4b37e --- .../com/android/internal/telephony/TelephonyProperties.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index b08238e2e41bc..e7c3ad6360b9c 100755 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -202,6 +202,12 @@ public interface TelephonyProperties */ static final String CALLS_ON_IMS_ENABLED_PROPERTY = "persist.radio.calls.on.ims"; + /** + * Specify if Android supports CSVT calls. + */ + static final String PROPERTY_CSVT_ENABLED = "persist.radio.csvt.enabled"; + + /** * Ignore RIL_UNSOL_NITZ_TIME_RECEIVED completely, used for debugging/testing. */ From b9ba4718017262eaea8c1af85596a0d07266acd5 Mon Sep 17 00:00:00 2001 From: Suresh Koleti Date: Fri, 25 Jan 2013 13:34:28 +0530 Subject: [PATCH 060/204] Telephony(MultiSim): Add support for emergency calls Populate ecclist by reading ril.ecclist corresponds to each subscription. If dialed number is present in consolidated ecclist then mark as emergency number. Change-Id: Ibba48a930e29dac0d80d0c8add2e01214a9bf9c3 CRs-fixed: 445415 --- .../java/android/telephony/PhoneNumberUtils.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index 1a6fae278a168..063311918a4ec 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -1699,9 +1699,18 @@ private static boolean isEmergencyNumberInternal(String number, // to the list. number = extractNetworkPortionAlt(number); - // retrieve the list of emergency numbers - // check read-write ecclist property first - String numbers = SystemProperties.get("ril.ecclist"); + String numbers = ""; + for (int i = 0; i < MSimTelephonyManager.getDefault().getPhoneCount(); i++) { + // retrieve the list of emergency numbers + // check read-write ecclist property first + String ecclist = (i == 0) ? "ril.ecclist" : ("ril.ecclist" + i); + + if (!TextUtils.isEmpty(numbers)) { + numbers = numbers + ","; + } + numbers = numbers + SystemProperties.get(ecclist); + } + if (TextUtils.isEmpty(numbers)) { // then read-only ecclist property since old RIL only uses this numbers = SystemProperties.get("ro.ril.ecclist"); From 4d88cdbf30ba48101d539cb42f129c77f7e69b4e Mon Sep 17 00:00:00 2001 From: Sandeep Kunta Date: Sat, 10 Aug 2013 20:55:38 +0530 Subject: [PATCH 061/204] Telephony: Add support for NETWORK_TYPE_GSM Add support for NETWORK_TYPE_GSM in TelephonyManager and corresponding mapping in ServicState.java so that when application queries getVoiceNetworkType() and currently camped rat is GSM, they get network mode as GSM instead of network mode unknown. Change-Id: I5e971c625532696776b9555ad8cfd85eba4fc423 CRs-Fixed: 526435 --- telephony/java/android/telephony/ServiceState.java | 2 ++ telephony/java/android/telephony/TelephonyManager.java | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 2dbfb298b0f1e..6754ce3060ecb 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -814,6 +814,8 @@ private int rilRadioTechnologyToNetworkType(int rt) { return TelephonyManager.NETWORK_TYPE_DCHSPAP; case ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA: return TelephonyManager.NETWORK_TYPE_TD_SCDMA; + case ServiceState.RIL_RADIO_TECHNOLOGY_GSM: + return TelephonyManager.NETWORK_TYPE_GSM; default: return TelephonyManager.NETWORK_TYPE_UNKNOWN; } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index a1c23d00def13..d769a2d696fe5 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -645,6 +645,8 @@ public static String getTelephonyProperty(String property, int index, String def public static final int NETWORK_TYPE_EHRPD = 14; /** Current network is HSPA+ */ public static final int NETWORK_TYPE_HSPAP = 15; + /** Current network is GSM {@hide} */ + public static final int NETWORK_TYPE_GSM = 16; /** Current network is TD_SCDMA {@hide} */ public static final int NETWORK_TYPE_TD_SCDMA = 17; /** Current network is DC-HSPAP @@ -755,6 +757,7 @@ public void toggleLTE(boolean on) { public static int getNetworkClass(int networkType) { switch (networkType) { case NETWORK_TYPE_GPRS: + case NETWORK_TYPE_GSM: case NETWORK_TYPE_EDGE: case NETWORK_TYPE_CDMA: case NETWORK_TYPE_1xRTT: @@ -825,6 +828,8 @@ public static String getNetworkTypeName(int type) { return "HSPA+"; case NETWORK_TYPE_DCHSPAP: return "DCHSPAP"; + case NETWORK_TYPE_GSM: + return "GSM"; case NETWORK_TYPE_TD_SCDMA: return "TD_SCDMA"; default: From a781753a22ce63be776bfb582267f457f104867a Mon Sep 17 00:00:00 2001 From: Sandeep Gutta Date: Wed, 21 Aug 2013 14:09:13 +0530 Subject: [PATCH 062/204] Telephony(MSIM): Define invalid subscription constant Define a new constant for invalid subscription id. Change-Id: I7bc433d5f24c70b710cde7ef5ac362b7ee945d2d CRs-Fixed: 529780 --- .../java/com/android/internal/telephony/MSimConstants.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telephony/java/com/android/internal/telephony/MSimConstants.java b/telephony/java/com/android/internal/telephony/MSimConstants.java index e9b77d7e888a0..9d35fd3538738 100644 --- a/telephony/java/com/android/internal/telephony/MSimConstants.java +++ b/telephony/java/com/android/internal/telephony/MSimConstants.java @@ -33,6 +33,8 @@ public class MSimConstants { public static final int DEFAULT_SUBSCRIPTION = 0; + public static final int INVALID_SUBSCRIPTION = -1; + public static final int RIL_CARD_MAX_APPS = 8; public static final int DEFAULT_CARD_INDEX = 0; From 421562923b8479e8bec44b2816e5940cde132665 Mon Sep 17 00:00:00 2001 From: Alex Yakavenka Date: Mon, 26 Aug 2013 12:49:03 -0700 Subject: [PATCH 063/204] Add onDataRatChanged trigger to DcTracker It is required to reload apns when data rat switches from gsm to cdma Change-Id: Ifdb04d0c8be325a226dbc707a3fa8c8c697089fa CRs-Fixed: 530277 --- telephony/java/com/android/internal/telephony/DctConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java index 1ef46fa724230..892864043d5dd 100644 --- a/telephony/java/com/android/internal/telephony/DctConstants.java +++ b/telephony/java/com/android/internal/telephony/DctConstants.java @@ -98,10 +98,10 @@ public enum Activity { public static final int EVENT_DATA_SETUP_COMPLETE_ERROR = BASE + 35; public static final int EVENT_TETHERED_MODE_STATE_CHANGED = BASE + 36; public static final int EVENT_MODEM_DATA_PROFILE_READY= BASE + 37; - public static final int CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA = BASE + 38; public static final int CMD_ENABLE_MOBILE_PROVISIONING = BASE + 39; public static final int CMD_IS_PROVISIONING_APN = BASE + 40; + public static final int EVENT_DATA_RAT_CHANGED = BASE + 41; /***** Constants *****/ From 737ff0b2188378c30e31ff6200a7ad1e641ca1c7 Mon Sep 17 00:00:00 2001 From: Mingming Yin Date: Wed, 5 Jun 2013 11:55:46 -0700 Subject: [PATCH 064/204] frameworks/base: Add constants for call_state and vsid For DSDA, CallManager will call setParameters() to indicate the call state changes between CS Multimode call, CS GSM only call and IMS Multimode. Add constants for call_state and vsid keys. Add pre-defined VSID and call state constants. Change-Id: I6add5f13d4a2ad5eacdf0750bbd402128d86f7cd --- media/java/android/media/AudioManager.java | 49 ++++++++++++++++++++++ media/java/android/media/AudioSystem.java | 26 ++++++++++++ 2 files changed, 75 insertions(+) diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index ca9471c6f7b3d..b8f03a043055f 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1,4 +1,7 @@ /* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -1475,6 +1478,52 @@ public int getMode() { */ public static final int MODE_IN_COMMUNICATION = AudioSystem.MODE_IN_COMMUNICATION; + /* Calls states for Voice calls */ + /** + * @hide Call state for inactive call state. + */ + public static final int CALL_INACTIVE = AudioSystem.CALL_INACTIVE; + /** + * @hide Call state for active call state. + */ + public static final int CALL_ACTIVE = AudioSystem.CALL_ACTIVE; + /** + * @hide Call state for hold call state. + */ + public static final int CALL_HOLD = AudioSystem.CALL_HOLD; + /** + * @hide Call state for local call hold state. + */ + public static final int CALL_LOCAL_HOLD = AudioSystem.CALL_LOCAL_HOLD; + + + /* VSIDS for IMS, Multimode CS call and GSM CS call */ + /** + * @hide VSID for CS call, Multimode. + */ + public static final long VOICE_VSID = AudioSystem.VOICE_VSID; + /** + * @hide VSID for CS call, GSM-only. + */ + public static final long VOICE2_VSID = AudioSystem.VOICE2_VSID; + /** + * @hide VSID for IMS call, Multimode. + */ + public static final long IMS_VSID = AudioSystem.IMS_VSID; + + + /* Key used in setParameters for VSID and Call_state */ + /** + * @hide Key for vsid used in setParameters. + */ + public static final String VSID_KEY = AudioSystem.VSID_KEY; + + /** + * @hide Key for call_state used in setParameters. + */ + public static final String CALL_STATE_KEY = AudioSystem.CALL_STATE_KEY; + + /* Routing bits for setRouting/getRouting API */ /** * Routing audio output to earpiece diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 5848684d22c84..f0ee7a84834a5 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -1,4 +1,7 @@ /* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -89,6 +92,29 @@ public class AudioSystem public static final int NUM_MODES = 4; + /* Call states for Voice calls */ + /* @hide Call state for inactive call state. */ + public static final int CALL_INACTIVE = 0x1; + /* @hide Call state for active call state. */ + public static final int CALL_ACTIVE = 0x2; + /* @hide Call state for hold call state. */ + public static final int CALL_HOLD = 0x3; + /* @hide Call state for local hold call state. */ + public static final int CALL_LOCAL_HOLD = 0x4; + + /* @hide VSID for CS voice, Multimode */ + public static final long VOICE_VSID = 0x10C01000; + /* @hide VSID for CS Voice GSM-Only */ + public static final long VOICE2_VSID = 0x10DC1000; + /* @hide VSID for IMS Multimode */ + public static final long IMS_VSID = 0x10C02000; + + /* @hide Key for vsid used in setParameters */ + public static final String VSID_KEY = "vsid"; + + /* @hide Key for call_state used in setParameters */ + public static final String CALL_STATE_KEY = "call_state"; + /* Routing bits for the former setRouting/getRouting API */ /** @deprecated */ @Deprecated public static final int ROUTE_EARPIECE = (1 << 0); From 084877b1abe069e93f9240eb8df50d8822541d62 Mon Sep 17 00:00:00 2001 From: Mingming Yin Date: Tue, 26 Mar 2013 12:18:53 -0700 Subject: [PATCH 065/204] audio: Manage audio focus for QCHAT - Cherry-picked from the commit with commit ID: c14c6156e879ec1c3f83f6a2cc31dac1d22147a2 - FR-fixed: 8965 Change-Id: I51c554b82c6177b7d3e845bdc8970825b5d1198a --- media/java/android/media/AudioService.java | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 98c52c064b578..523b25e922325 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -4690,6 +4690,25 @@ private boolean canReassignAudioFocusTo(String clientId) { return true; } + /* Constant to identify focus stack entry that is used to hold the audio focus for QCHAT client + */ + private static final String CLIENT_ID_QCHAT = "QCHAT"; + + /** + * Helper function: + * Returns true if the system is in a state where the focus can be reevaluated, false otherwise. + */ + private boolean canReassignAudioFocusFromQchat(int streamType, String clientId) { + // Focus request is rejected for Music Player and for QChat client if the focus is already + // acquired by a QChat client + if (!mFocusStack.isEmpty() && + mFocusStack.peek().mClientId.contains(CLIENT_ID_QCHAT) && + (clientId.contains(CLIENT_ID_QCHAT) || (streamType == AudioManager.STREAM_MUSIC))) { + return false; + } + return true; + } + /** * Inner class to monitor audio focus client deaths, and remove them from the audio focus * stack if necessary. @@ -4731,6 +4750,9 @@ public int requestAudioFocus(int mainStreamType, int focusChangeHint, IBinder cb if (!canReassignAudioFocusTo(clientId)) { return AudioManager.AUDIOFOCUS_REQUEST_FAILED; } + if (!canReassignAudioFocusFromQchat(mainStreamType, clientId)) { + return AudioManager.AUDIOFOCUS_REQUEST_FAILED; + } // handle the potential premature death of the new holder of the focus // (premature death == death before abandoning focus) From 4d46205cad07da19873e3a166a3ebbb8a2ea9e81 Mon Sep 17 00:00:00 2001 From: Vidyakumar Athota Date: Tue, 30 Jul 2013 11:33:08 -0700 Subject: [PATCH 066/204] frameworks/base: Add support for QCHAT call. - Add VSID for QCHAT. - Add a key which can be used with getParameters() to query all call states. Change-Id: If7be9467013700b220c9b10c6236a99d56f7a8cc --- media/java/android/media/AudioManager.java | 9 +++++++++ media/java/android/media/AudioSystem.java | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index b8f03a043055f..aeec78ffebd0d 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1510,6 +1510,10 @@ public int getMode() { * @hide VSID for IMS call, Multimode. */ public static final long IMS_VSID = AudioSystem.IMS_VSID; + /** + * @hide VSID for QCHAT call. + */ + public static final long QCHAT_VSID = AudioSystem.QCHAT_VSID; /* Key used in setParameters for VSID and Call_state */ @@ -1523,6 +1527,11 @@ public int getMode() { */ public static final String CALL_STATE_KEY = AudioSystem.CALL_STATE_KEY; + /** + * @hide Key for all_call_states used in getParameters. + */ + public static final String ALL_CALL_STATES_KEY = AudioSystem.ALL_CALL_STATES_KEY; + /* Routing bits for setRouting/getRouting API */ /** diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index f0ee7a84834a5..3a6c0af9ff173 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -108,6 +108,8 @@ public class AudioSystem public static final long VOICE2_VSID = 0x10DC1000; /* @hide VSID for IMS Multimode */ public static final long IMS_VSID = 0x10C02000; + /* @hide VSID for QCHAT */ + public static final long QCHAT_VSID = 0x10803000; /* @hide Key for vsid used in setParameters */ public static final String VSID_KEY = "vsid"; @@ -115,6 +117,9 @@ public class AudioSystem /* @hide Key for call_state used in setParameters */ public static final String CALL_STATE_KEY = "call_state"; + /* @hide Key for all_call_states used in getParameters */ + public static final String ALL_CALL_STATES_KEY = "all_call_states"; + /* Routing bits for the former setRouting/getRouting API */ /** @deprecated */ @Deprecated public static final int ROUTE_EARPIECE = (1 << 0); From cf72e39a556cce256ffae7a95028e136ec415cc3 Mon Sep 17 00:00:00 2001 From: SanthoshHE Date: Tue, 23 Jul 2013 11:25:43 +0530 Subject: [PATCH 067/204] media: Configure audio encode parameters only for valid audio codec Added extra check for audio codec in profile Change-Id: Idc83bcc6d77361bd298bbff3eee1d0132e5498ea CRs-fixed: 513887 --- media/java/android/media/MediaRecorder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 04ca39a78a894..06d9109293f6a 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -357,7 +357,7 @@ public void setProfile(CamcorderProfile profile) { profile.quality <= CamcorderProfile.QUALITY_TIME_LAPSE_QVGA) { // Nothing needs to be done. Call to setCaptureRate() enables // time lapse video recording. - } else { + } else if (profile.audioCodec >= 0) { setAudioEncodingBitRate(profile.audioBitRate); setAudioChannels(profile.audioChannels); setAudioSamplingRate(profile.audioSampleRate); From f60d36474dc36ab542b8d9b6d50f2ab89a338b1a Mon Sep 17 00:00:00 2001 From: Krishnankutty Kolathappilly Date: Tue, 30 Apr 2013 18:41:48 -0700 Subject: [PATCH 068/204] frameworks/base: Add wifi display to fixed volume devices Wifi display should be treated as device with fixed volume like HDMI. User should not be able to change the volume on device. Volume change should be supported only on the end device CRs-Fixed: 480334 Change-Id: I2e41e9aef01167d1bdca3bca09ed863834dae1d8 --- media/java/android/media/AudioService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 523b25e922325..9ffe77ed80fbc 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -444,7 +444,8 @@ public void onError(int error) { // Devices for which the volume is fixed and VolumePanel slider should be disabled final int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_AUX_DIGITAL | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET | - AudioSystem.DEVICE_OUT_ALL_USB; + AudioSystem.DEVICE_OUT_ALL_USB | + AudioSystem.DEVICE_OUT_PROXY; // TODO merge orientation and rotation private final boolean mMonitorOrientation; From a6c7dcedabf4a92b33a4aaa3ebb22074676960dc Mon Sep 17 00:00:00 2001 From: Narsinga Rao Chella Date: Tue, 13 Aug 2013 16:56:09 -0700 Subject: [PATCH 069/204] frameworks/base: Add support for QCHAT concurrencies. - Add setParameters() support in Audio Service. - Handle audio focus for QCHAT to support concurrencies with telephony calls and music player. Change-Id: I2c317948c3b1c508f07787d473d40fb9a09f4b91 --- media/java/android/media/AudioManager.java | 7 +- media/java/android/media/AudioService.java | 163 ++++++++++++++++++-- media/java/android/media/IAudioService.aidl | 2 + 3 files changed, 159 insertions(+), 13 deletions(-) diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index aeec78ffebd0d..4213af1184bd8 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1681,7 +1681,12 @@ public void adjustLocalOrRemoteStreamVolume(int streamType, int direction) { * */ public void setParameters(String keyValuePairs) { - AudioSystem.setParameters(keyValuePairs); + IAudioService service = getService(); + try { + service.setParameters(keyValuePairs); + } catch (RemoteException e) { + Log.e(TAG, "Error in setParameters due to "+e); + } } /** diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 9ffe77ed80fbc..ab376c25553f8 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -4523,11 +4523,10 @@ private void discardAudioFocusOwner() { private void notifyTopOfAudioFocusStack() { // notify the top of the stack it gained focus if (!mFocusStack.empty() && (mFocusStack.peek().mFocusDispatcher != null)) { - String clientId = mFocusStack.peek().mClientId; - if (canReassignAudioFocusTo(clientId)) { + if (canReassignAudioFocus(mFocusStack.peek().mClientId)) { try { mFocusStack.peek().mFocusDispatcher.dispatchAudioFocusChange( - AudioManager.AUDIOFOCUS_GAIN, clientId); + AudioManager.AUDIOFOCUS_GAIN, mFocusStack.peek().mClientId); } catch (RemoteException e) { Log.e(TAG, "Failure to signal gain of audio control focus due to "+ e); e.printStackTrace(); @@ -4677,24 +4676,88 @@ private void removeFocusStackEntryForClient(IBinder cb) { /** * Helper function: - * Returns true if the system is in a state where the focus can be reevaluated, false otherwise. + * Gets the call states from HAL using the AudioSystem.getParameters() function, + * parses the return string and updates the local call state variables. + * Returns true if the system is in a state where the focus can be granted to + * QCHAT call, false otherwise. */ - private boolean canReassignAudioFocusTo(String clientId) { - // focus requests are rejected during a phone call or when the phone is ringing - // this is equivalent to IN_VOICE_COMM_FOCUS_ID having the focus - if (IN_VOICE_COMM_FOCUS_ID.equals(clientId)) { - return true; + private boolean isQchatCallAllowed() + { + int voiceCallState = 0; + int voice2CallState = 0; + int volteCallState = 0; + int qchatCallState = 0; + + try { + String keyValuePair, value; + String[] fields, tokens; + long vsid; + int callState; + + // AudioSystem.getParameters() returns a value in the format: + // "all_call_states=281022464:1,282857472:1,281026560:1,276836352:1" + keyValuePair = AudioSystem.getParameters(AudioManager.ALL_CALL_STATES_KEY); + if (!keyValuePair.startsWith(AudioManager.ALL_CALL_STATES_KEY)) { + return false; + } + + value = keyValuePair.substring(AudioManager.ALL_CALL_STATES_KEY.length()+1); + fields = value.split(","); + for (String item : fields) { + tokens = item.split(":"); + vsid = Long.decode(tokens[0]).longValue(); + callState = Integer.decode(tokens[1]).intValue(); + + if (vsid == AudioManager.VOICE_VSID) + voiceCallState = callState; + else if (vsid == AudioManager.VOICE2_VSID) + voice2CallState = callState; + else if (vsid == AudioManager.IMS_VSID) + volteCallState = callState; + else if (vsid == AudioManager.QCHAT_VSID) + qchatCallState = callState; + else + Log.e(TAG, "Unrecognized VSID value "+vsid); + } + + Log.i(TAG, "voiceCallState=" + voiceCallState + " voice2CallState=" + voice2CallState); + Log.i(TAG, "volteCallState=" + volteCallState + " qchatCallState=" + qchatCallState); + } catch (Exception e) { + Log.e(TAG, "Could not get call states from HAL due to "+e); } - if (!mFocusStack.isEmpty() && IN_VOICE_COMM_FOCUS_ID.equals(mFocusStack.peek().mClientId)) { + + if ((voiceCallState == AudioManager.CALL_ACTIVE ) || + (voice2CallState == AudioManager.CALL_ACTIVE ) || + (volteCallState == AudioManager.CALL_ACTIVE ) || + (qchatCallState == AudioManager.CALL_ACTIVE )) { return false; } - return true; + else { + return true; + } } /* Constant to identify focus stack entry that is used to hold the audio focus for QCHAT client */ private static final String CLIENT_ID_QCHAT = "QCHAT"; + /** + * Helper function: + * Returns true if the system is in a state where the focus can be reevaluated, false otherwise. + */ + private boolean canReassignAudioFocus(String clientId) { + // focus requests are rejected during a phone call or when the phone is ringing + // this is equivalent to IN_VOICE_COMM_FOCUS_ID having the focus. + // Also focus request is granted to QCHAT client when the CS/IMS calls are on HOLD. + if (!mFocusStack.isEmpty() && IN_VOICE_COMM_FOCUS_ID.equals(mFocusStack.peek().mClientId)) { + if (clientId.contains(CLIENT_ID_QCHAT) && isQchatCallAllowed()) + return true; + else + return false; + } + return true; + } + /** * Helper function: * Returns true if the system is in a state where the focus can be reevaluated, false otherwise. @@ -4748,7 +4811,7 @@ public int requestAudioFocus(int mainStreamType, int focusChangeHint, IBinder cb } synchronized(mAudioFocusLock) { - if (!canReassignAudioFocusTo(clientId)) { + if (!canReassignAudioFocus(clientId)) { return AudioManager.AUDIOFOCUS_REQUEST_FAILED; } if (!canReassignAudioFocusFromQchat(mainStreamType, clientId)) { @@ -4836,6 +4899,82 @@ public void unregisterAudioFocusClient(String clientId) { } } + /** + * Helper function: + * Parses the input Key-Value pairs and handles the audio focus to QCHAT if needed. + */ + private void handleFocusForQchat(String keyValuePairs) { + long vsid = 0; + int callState = 0; + // Parse VSID and Call State from the input string + try { + String[] pairs; + String[] fields; + + pairs = keyValuePairs.split(";"); + for (String item : pairs) { + Log.d(TAG, "keyValuePair is "+item); + fields = item.split("="); + if (item.startsWith(AudioManager.VSID_KEY)) { + vsid = Long.decode(fields[1]).longValue(); + } + else if (item.startsWith(AudioManager.CALL_STATE_KEY)) { + callState = Integer.decode(fields[1]).intValue(); + } + } + } catch (Exception e) { + Log.e(TAG, "Invalid number format "+e); + return; + } + + // Check if any of the telephony calls are UN-HOLD so that + // QCHAT call should lose focus automatically + if (((vsid == AudioManager.VOICE_VSID) || + (vsid == AudioManager.VOICE2_VSID) || + (vsid == AudioManager.IMS_VSID)) && + (callState == AudioManager.CALL_ACTIVE)) { + + Log.d(TAG, "Telephony call is going to ACTIVE state, see if QCHAT needs to be closed "); + // Notify the QCHAT client that it is losing focus if it is the + // current top of the stack; Also remove the focus stack entry for QCHAT. + synchronized(mAudioFocusLock) { + if ((!mFocusStack.isEmpty()) && + (mFocusStack.peek().mClientId.contains(CLIENT_ID_QCHAT)) && + (mFocusStack.peek().mFocusDispatcher != null)) { + try { + Log.d(TAG, "Dispatch focus loss to QCHAT "); + mFocusStack.peek().mFocusDispatcher.dispatchAudioFocusChange( + -1 * mFocusStack.peek().mFocusChangeType, /* loss and gain codes + are inverse of each other */ + mFocusStack.peek().mClientId); + } catch (RemoteException e) { + Log.e(TAG, " Failure to signal loss of focus due to "+ e); + e.printStackTrace(); + } + + FocusStackEntry fse = mFocusStack.pop(); + fse.unlinkToDeath(); + } + } + } + } + + /** + * Sets a variable number of parameter values to audio hardware. + * + * @param keyValuePairs list of parameters key value pairs in the form: + * key1=value1;key2=value2;... + * + */ + public void setParameters(String keyValuePairs) { + + if (keyValuePairs.contains(AudioManager.VSID_KEY)) { + handleFocusForQchat(keyValuePairs); + } + + AudioSystem.setParameters(keyValuePairs); + } + //========================================================================================== // RemoteControl diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index fda8c1bd2eded..11f0004ec5795 100644 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -208,4 +208,6 @@ interface IAudioService { AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer); boolean isCameraSoundForced(); + + void setParameters(String keyValuePairs); } From a69d6c40748fd3e64c468ad000592688899c1a70 Mon Sep 17 00:00:00 2001 From: Banavathu Srinivas Naik Date: Mon, 26 Nov 2012 17:55:50 +0530 Subject: [PATCH 070/204] Frameworks: Do not send Radio Power Off on SIM_RESET Changes made to not to send radio power off during refresh app reset. Change-Id: I83b7063a86ce9b380c7aeb0c140a4967d205d93b CRs-Fixed: 441924 Conflicts: core/res/res/values/symbols.xml --- core/res/res/values/config.xml | 4 ++++ core/res/res/values/symbols.xml | 1 + 2 files changed, 5 insertions(+) diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 5588eb0d649e5..94f64827a9195 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1071,6 +1071,10 @@ false + + + true + true diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 00df1578d75c5..a0b340328c59b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -280,6 +280,7 @@ + From 37b6d7fb64c873ec12dc08b6bc8b4d57768a32c0 Mon Sep 17 00:00:00 2001 From: Chaitanya Saggurthi Date: Thu, 4 Jul 2013 20:22:08 +0530 Subject: [PATCH 071/204] Telephony(MSIM): Add prompt support for SMS 1) Add prompt option in SMS multi sim settings. 2) New iterface API to get SMS prompt is enabled or not. 3) Disply prompt while sending SMS, if user selects prompt mode in multi sim settings. CRs-fixed: 474694 Change-Id: Iea9e8a4ea4f413316604a3d66ece624eab75ee26 --- core/java/android/provider/Settings.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index dd7fbc4a54a89..db83f94fcfcd6 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6947,6 +6947,15 @@ public static boolean putFloat(ContentResolver cr, String name, float value) { */ public static final String MULTI_SIM_SMS_SUBSCRIPTION = "multi_sim_sms"; + /** + * Used to provide option to user to select subscription during send SMS. + * The value 1 - enable, 0 - disable + * @hide + */ + public static final String MULTI_SIM_SMS_PROMPT = "multi_sim_sms_prompt"; + + + /** User preferred subscriptions setting. * This holds the details of the user selected subscription from the card and * the activation status. Each settings string have the coma separated values From f62496990490353f36a0a353ced7891b77e9ddfc Mon Sep 17 00:00:00 2001 From: Sudheer Reddy Yampalla Date: Tue, 19 Mar 2013 11:35:45 +0530 Subject: [PATCH 072/204] Telephony: Add support for tune away and priority sub Add constants for tune away and priority subscription CRs-fixed: 464483 Change-Id: I790cfdcd9a1dee946502349084a4d8138d2144ec --- core/java/android/provider/Settings.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index db83f94fcfcd6..099593b38efd4 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6964,6 +6964,20 @@ public static boolean putFloat(ContentResolver cr, String name, float value) { */ public static final String[] MULTI_SIM_USER_PREFERRED_SUBS = {"user_preferred_sub1", "user_preferred_sub2","user_preferred_sub3"}; + + /** + * Subscription to be used decide priority sub on a multi sim device. The supported values + * are 0 = SUB1, 1 = SUB2, 2 = SUB3. + * @hide + */ + public static final String MULTI_SIM_PRIORITY_SUBSCRIPTION = "multi_sim_priority"; + + /** + * To know the status of tune away. The supported values + * are false = disable, true = enable. + * @hide + */ + public static final String TUNE_AWAY_STATUS = "tune_away"; } /** From bf5a4d89439267f6e0268a30a3be3f2a7d60f4ef Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Tue, 8 Oct 2013 16:37:21 -0700 Subject: [PATCH 073/204] Fix compilation after upstream merge Change-Id: Ifde1ee07d3968b16af7ccc311b0ed615931ea921 --- .../systemui/statusbar/policy/MSimNetworkController.java | 2 +- .../android/systemui/statusbar/policy/NetworkController.java | 2 +- .../com/android/systemui/statusbar/tablet/TabletStatusBar.java | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java index 470ece5693583..4aebaa165a880 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java @@ -58,7 +58,7 @@ public class MSimNetworkController extends NetworkController { // debug static final String TAG = "StatusBar.MSimNetworkController"; - static final boolean DEBUG = true; + static final boolean DEBUG = false; static final boolean CHATTY = true; // additional diagnostics, but not logspew // telephony diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 95ab841c054dd..1c88fe691f744 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -63,7 +63,7 @@ public class NetworkController extends BroadcastReceiver { // debug static final String TAG = "StatusBar.NetworkController"; - static final boolean DEBUG = true; + static final boolean DEBUG = false; static final boolean CHATTY = true; // additional diagnostics, but not logspew // telephony diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java index 9a4d5a9b7a22b..f8e8d8a082104 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -605,7 +605,8 @@ protected View makeStatusBarView() { mMSimNetworkController.addSignalCluster(mSimSignalCluster, i); } } else { - mSignalCluster = (SignalClusterView)sb.findViewById(R.id.signal_cluster); + final SignalClusterView signalCluster = + (SignalClusterView)sb.findViewById(R.id.signal_cluster); mNetworkController = new NetworkController(mContext); mNetworkController.addSignalCluster(signalCluster); From 9d639245a7ffcc1889edc58415a93b35efc54a90 Mon Sep 17 00:00:00 2001 From: William Roberts Date: Mon, 7 Oct 2013 17:56:43 -0400 Subject: [PATCH 074/204] Correcting NULL pointer when callerApp is not set Change-Id: Ia6570f428141de32d564dd190bbcf93a5d640fd1 JIRA: CYAN-2458 Issue: https://jira.cyanogenmod.org/browse/CYAN-2458 --- .../java/com/android/server/am/ActivityManagerService.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 848e09486b00d..9589375f957ee 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -11815,8 +11815,12 @@ public Intent registerReceiver(IApplicationThread caller, String callerPackage, "Receiver requested to register for user " + userId + " was previously registered for user " + rl.userId); } + + boolean isSystem = callerApp != null ? + (callerApp.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0 : false; + BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, - permission, callingUid, userId, (callerApp.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0); + permission, callingUid, userId, isSystem); rl.add(bf); if (!bf.debugCheck()) { Slog.w(TAG, "==> For Dynamic broadast"); From afeba31a686c97d2b06a3a50ce5240bfac181e9c Mon Sep 17 00:00:00 2001 From: Danesh M Date: Fri, 18 Oct 2013 11:20:47 -0700 Subject: [PATCH 075/204] Frameworks : Fix face detection I337a7a2e8b124aac76f52abcc0edd8af9b0b0e29 introduced the ifdef's at the wrong location. This patchset addresses it. Change-Id: I6b19fb96076bdc62b2ca57d1ccaf97f0cb901d67 --- core/jni/android_hardware_Camera.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index 6ca217f13752b..de7666b675ab9 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -386,6 +386,7 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m env->SetObjectField(face, fields.face_rect, rect); env->SetIntField(face, fields.face_score, metadata->faces[i].score); +#ifdef QCOM_HARDWARE jobject point1 = env->NewObject(mPointClass, fields.point_constructor); env->SetIntField(point1, fields.point_x, metadata->faces[i].left_eye[0]); env->SetIntField(point1, fields.point_y, metadata->faces[i].left_eye[1]); @@ -403,7 +404,6 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m env->SetIntField(face, fields.face_id, metadata->faces[i].id); -#ifdef QCOM_HARDWARE if (mIsQcFace) { env->SetIntField(face, fields.face_sm_degree, metadata->faces[i].smile_degree); env->SetIntField(face, fields.face_sm_score, metadata->faces[i].smile_score); @@ -418,14 +418,14 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m env->SetIntField(face, fields.face_left_right_gaze, metadata->faces[i].left_right_gaze); env->SetIntField(face, fields.face_top_bottom_gaze, metadata->faces[i].top_bottom_gaze); } + env->DeleteLocalRef(point1); + env->DeleteLocalRef(point2); + env->DeleteLocalRef(point3); + #endif env->DeleteLocalRef(face); env->DeleteLocalRef(rect); - - env->DeleteLocalRef(point1); - env->DeleteLocalRef(point2); - env->DeleteLocalRef(point3); } env->CallStaticVoidMethod(mCameraJClass, fields.post_event, mCameraJObjectWeak, msgType, 0, 0, obj); From 0b8f6c01ae96a160b1631f1fcb45c153dfa0de66 Mon Sep 17 00:00:00 2001 From: Danesh Mondegarian Date: Sun, 20 Oct 2013 00:34:48 -0700 Subject: [PATCH 076/204] DeviceKeyHandler : Allow handling keyevents while screen off Some devices require the keyevents to be processed while the screen is off, this patchset addresses that by moving the filter up in the call hierarchy. Change-Id: If71beecc81aa5e453dcd08aba72b7bea5c210590 --- .../policy/impl/PhoneWindowManager.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 209f4da6cb573..d4a4db9473544 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -2272,18 +2272,6 @@ public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int p mHandler.removeCallbacks(mBackLongPress); } - // Specific device key handling - if (mDeviceKeyHandler != null) { - try { - // The device only should consume known keys. - if (mDeviceKeyHandler.handleKeyEvent(event)) { - return -1; - } - } catch (Exception e) { - Slog.w(TAG, "Could not dispatch event to device key handler", e); - } - } - // First we always handle the home key here, so applications // can never break it, although if keyguard is on, we do let // it handle it, because that gives us the correct 5 second @@ -4189,6 +4177,18 @@ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean i return result; } + // Specific device key handling + if (mDeviceKeyHandler != null) { + try { + // The device only should consume known keys. + if (mDeviceKeyHandler.handleKeyEvent(event)) { + return 0; + } + } catch (Exception e) { + Slog.w(TAG, "Could not dispatch event to device key handler", e); + } + } + // Handle special keys. switch (keyCode) { case KeyEvent.KEYCODE_ENDCALL: { From 170a6daba1b00bc9e6217b4a01fe48c40758960f Mon Sep 17 00:00:00 2001 From: Veeti Paananen Date: Sun, 20 Oct 2013 18:50:10 +0300 Subject: [PATCH 077/204] Fix removal of dock battery views in PhoneStatusBar removeView is not recursive. Find and remove the dock views from their direct parent. Fixes inconsistent paddings/margins with the wi-fi indicator on tablets. Change-Id: I56745059aaf84b1e52b6a4fd8806481beae0daff --- .../systemui/statusbar/phone/PhoneStatusBar.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 479bd7ada2262..d8abfecda8636 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -641,12 +641,10 @@ public boolean onTouch(View v, MotionEvent event) { mDockBatteryController.addStateChangedCallback(callback); } else { // Remove dock battery icons if device doesn't hava dock battery support - View v = mStatusBarView.findViewById(R.id.dock_battery); - if (v != null) mStatusBarView.removeView(v); - v = mStatusBarView.findViewById(R.id.dock_battery_text); - if (v != null) mStatusBarView.removeView(v); - v = mStatusBarView.findViewById(R.id.circle_dock_battery); - if (v != null) mStatusBarView.removeView(v); + ViewGroup cluster = (ViewGroup) mStatusBarView.findViewById(R.id.signal_battery_cluster); + cluster.removeView(cluster.findViewById(R.id.dock_battery)); + cluster.removeView(cluster.findViewById(R.id.dock_battery_text)); + cluster.removeView(cluster.findViewById(R.id.circle_dock_battery)); mCircleDockBattery = null; } From 98dab839114cda2254caa38ef307373cbfe9bf57 Mon Sep 17 00:00:00 2001 From: Veeti Paananen Date: Sun, 20 Oct 2013 18:54:35 +0300 Subject: [PATCH 078/204] Fix misspelled comment Change-Id: Id13737b3a40eeee70ec0816aebe551d34ce89691 --- .../com/android/systemui/statusbar/phone/PhoneStatusBar.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index d8abfecda8636..ddde79e523f18 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -640,7 +640,7 @@ public boolean onTouch(View v, MotionEvent event) { (DockBatteryController.DockBatteryStateChangeCallback) mCircleDockBattery; mDockBatteryController.addStateChangedCallback(callback); } else { - // Remove dock battery icons if device doesn't hava dock battery support + // Remove dock battery icons if the device doesn't have dock battery support ViewGroup cluster = (ViewGroup) mStatusBarView.findViewById(R.id.signal_battery_cluster); cluster.removeView(cluster.findViewById(R.id.dock_battery)); cluster.removeView(cluster.findViewById(R.id.dock_battery_text)); From b9d164e992b8f91a4a89b2fd514fe097e0823a2a Mon Sep 17 00:00:00 2001 From: Veeti Paananen Date: Sun, 20 Oct 2013 21:41:02 +0300 Subject: [PATCH 079/204] Correct padding for status bar icons 4dp is used in AOSP. Change-Id: I7f97cb9feabe267c67722d600d0891ab2ce1a907 --- packages/SystemUI/res/values/dimens.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 77d0452bda7c3..abcf3a6af9291 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -220,7 +220,7 @@ 32dp - 2dip + 4dip -1dip From e622c7fa58684b5627533019ac16519b54492e9a Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Sun, 20 Oct 2013 06:12:00 -0700 Subject: [PATCH 080/204] qs: Add torch and GPS tiles by default if supported * New configuration variable config_enableTorch has been moved from the settings app that devices should overlay onto. Change-Id: I2e4cb81390548cf055eae2836280fe9bdc65f0b0 --- .../java/com/android/internal/util/cm/QSConstants.java | 2 ++ core/java/com/android/internal/util/cm/QSUtils.java | 10 ++++++++++ core/res/res/values/config.xml | 3 +++ core/res/res/values/symbols.xml | 2 ++ .../statusbar/phone/QuickSettingsController.java | 10 ++++++++++ 5 files changed, 27 insertions(+) diff --git a/core/java/com/android/internal/util/cm/QSConstants.java b/core/java/com/android/internal/util/cm/QSConstants.java index d6865b1c5a59d..77c91e4ac50d2 100644 --- a/core/java/com/android/internal/util/cm/QSConstants.java +++ b/core/java/com/android/internal/util/cm/QSConstants.java @@ -41,6 +41,8 @@ public class QSConstants { TILES_DEFAULT.add(TILE_SETTINGS); TILES_DEFAULT.add(TILE_WIFI); TILES_DEFAULT.add(TILE_MOBILEDATA); + TILES_DEFAULT.add(TILE_GPS); + TILES_DEFAULT.add(TILE_TORCH); TILES_DEFAULT.add(TILE_BATTERY); TILES_DEFAULT.add(TILE_AIRPLANE); TILES_DEFAULT.add(TILE_BLUETOOTH); diff --git a/core/java/com/android/internal/util/cm/QSUtils.java b/core/java/com/android/internal/util/cm/QSUtils.java index 6c8793ce4211f..2ea60cbd34b09 100644 --- a/core/java/com/android/internal/util/cm/QSUtils.java +++ b/core/java/com/android/internal/util/cm/QSUtils.java @@ -1,8 +1,10 @@ package com.android.internal.util.cm; +import android.R; import android.bluetooth.BluetoothAdapter; import android.content.ContentResolver; import android.content.Context; +import android.content.pm.PackageManager; import android.content.res.Resources; import android.hardware.Camera; import android.hardware.display.DisplayManager; @@ -67,6 +69,14 @@ public static boolean deviceSupportsCamera() { return Camera.getNumberOfCameras() > 0; } + public static boolean deviceSupportsGps(Context context) { + return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS); + } + + public static boolean deviceSupportsTorch(Context context) { + return context.getResources().getBoolean(com.android.internal.R.bool.config_enableTorch); + } + public static boolean adbEnabled(ContentResolver resolver) { return (Settings.Global.getInt(resolver, Settings.Global.ADB_ENABLED, 0)) == 1; } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 24b6d269dc5aa..4a4799a13bd41 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1296,4 +1296,7 @@ + + + false diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 9efa842eff59a..9995fb651c256 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2051,4 +2051,6 @@ + + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsController.java index a898942ff3881..640d0793398b1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsController.java @@ -158,6 +158,8 @@ void loadTiles() { boolean bluetoothSupported = QSUtils.deviceSupportsBluetooth(); boolean mobileDataSupported = QSUtils.deviceSupportsMobileData(mContext); boolean lteSupported = QSUtils.deviceSupportsLte(mContext); + boolean gpsSupported = QSUtils.deviceSupportsGps(mContext); + boolean torchSupported = QSUtils.deviceSupportsTorch(mContext); if (!bluetoothSupported) { TILES_DEFAULT.remove(TILE_BLUETOOTH); @@ -173,6 +175,14 @@ void loadTiles() { TILES_DEFAULT.remove(TILE_LTE); } + if (!gpsSupported) { + TILES_DEFAULT.remove(TILE_GPS); + } + + if (!torchSupported) { + TILES_DEFAULT.remove(TILE_TORCH); + } + // Read the stored list of tiles ContentResolver resolver = mContext.getContentResolver(); LayoutInflater inflater = LayoutInflater.from(mContext); From eaae8f7766e339af83ef37163d1e64cd66a5a676 Mon Sep 17 00:00:00 2001 From: Jorge Ruesga Date: Sat, 19 Oct 2013 14:12:39 +0200 Subject: [PATCH 081/204] QCFace: Fix package path Change-Id: I8282331003d0494bd5620cfb6e91f2dcfa708d30 Signed-off-by: Jorge Ruesga --- .../qualcomm => org/codeaurora}/camera/QCFace.java | 10 ---------- 1 file changed, 10 deletions(-) rename core/java/{com/qualcomm => org/codeaurora}/camera/QCFace.java (95%) diff --git a/core/java/com/qualcomm/camera/QCFace.java b/core/java/org/codeaurora/camera/QCFace.java similarity index 95% rename from core/java/com/qualcomm/camera/QCFace.java rename to core/java/org/codeaurora/camera/QCFace.java index 65bea7901cef1..9198c286ce863 100644 --- a/core/java/com/qualcomm/camera/QCFace.java +++ b/core/java/org/codeaurora/camera/QCFace.java @@ -19,14 +19,8 @@ package org.codeaurora.camera; -import android.hardware.Camera; - -import java.util.ArrayList; - import android.os.Bundle; -import android.os.SystemProperties; - /** * {@hide} Information about a Qaulcomm face identified through camera face * detection. @@ -56,10 +50,6 @@ public QCFace() { private int leftrightGaze = 0; private int topbottomGaze = 0; - private static final String STR_TRUE = "true"; - private static final String STR_FALSE = "false"; - private static final String STR_FACIAL_PROCESSING = "ro.qc.sdk.camera.facialproc"; - /** * The smilie degree for the detection of the face. * From dc9419845e0bc17db9a3398f6fc443768741bca4 Mon Sep 17 00:00:00 2001 From: Ethan Chen Date: Tue, 8 Oct 2013 15:20:02 -0700 Subject: [PATCH 082/204] Support GESTURE_SENSOR input device type with GestureService * The GESTURE_SENSOR input device type is meant to support touch sensors which are meant for gesture input only, very similar to a touchpad, but without the pointer capability. * Define separate service to handle gestures from GESTURE_SENSOR device type. Change-Id: I9b273df2a3cc141774d7f7cd81e43a90ea5b230b --- Android.mk | 1 + .../src/com/android/commands/input/Input.java | 4 +- .../service/gesture/IGestureService.aidl | 10 + core/java/android/view/InputDevice.java | 11 + core/res/res/values/config.xml | 3 + core/res/res/values/symbols.xml | 3 + services/input/InputReader.cpp | 8 + services/input/InputReader.h | 1 + .../java/com/android/server/SystemServer.java | 21 ++ .../server/gesture/GestureInputFilter.java | 319 ++++++++++++++++++ .../server/gesture/GestureService.java | 54 +++ 11 files changed, 434 insertions(+), 1 deletion(-) create mode 100644 core/java/android/service/gesture/IGestureService.aidl create mode 100644 services/java/com/android/server/gesture/GestureInputFilter.java create mode 100644 services/java/com/android/server/gesture/GestureService.java diff --git a/Android.mk b/Android.mk index 5094048850dcb..91df8ebdd8aa5 100644 --- a/Android.mk +++ b/Android.mk @@ -155,6 +155,7 @@ LOCAL_SRC_FILES += \ core/java/android/service/notification/INotificationListener.aidl \ core/java/android/service/dreams/IDreamManager.aidl \ core/java/android/service/dreams/IDreamService.aidl \ + core/java/android/service/gesture/IGestureService.aidl \ core/java/android/service/pie/IPieService.aidl \ core/java/android/service/pie/IPieActivationListener.aidl \ core/java/android/service/pie/IPieHostCallback.aidl \ diff --git a/cmds/input/src/com/android/commands/input/Input.java b/cmds/input/src/com/android/commands/input/Input.java index b24995d5da7bf..2c5562e78c1c3 100644 --- a/cmds/input/src/com/android/commands/input/Input.java +++ b/cmds/input/src/com/android/commands/input/Input.java @@ -78,13 +78,15 @@ private void run(String[] args) { return; } } else if (command.equals("touchscreen") || command.equals("touchpad") - || command.equals("touchnavigation")) { + || command.equals("touchnavigation") || command.equals("gesture")) { // determine input source int inputSource = InputDevice.SOURCE_TOUCHSCREEN; if (command.equals("touchpad")) { inputSource = InputDevice.SOURCE_TOUCHPAD; } else if (command.equals("touchnavigation")) { inputSource = InputDevice.SOURCE_TOUCH_NAVIGATION; + } else if (command.equals("gesture")) { + inputSource = InputDevice.SOURCE_GESTURE_SENSOR; } // determine subcommand if (args.length > 1) { diff --git a/core/java/android/service/gesture/IGestureService.aidl b/core/java/android/service/gesture/IGestureService.aidl new file mode 100644 index 0000000000000..56b4a866797dc --- /dev/null +++ b/core/java/android/service/gesture/IGestureService.aidl @@ -0,0 +1,10 @@ +package android.service.gesture; + +/** @hide */ +interface IGestureService { + + /** + * Register a listener for gesture sensor input. Gesture sensor input + * is then converted into input events for system consumption. + */ +} diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index 2a761c1b380f2..3acb9853b78c8 100644 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -219,6 +219,16 @@ public final class InputDevice implements Parcelable { */ public static final int SOURCE_TOUCH_NAVIGATION = 0x00200000 | SOURCE_CLASS_NONE; + /** + * The input source is a touch device whose motions should be interpreted as gestures. + * + * For example, an upward swipe should be treated the same as a swipe of the touchscreen. + * The same should apply for left, right, down swipes. Complex gestures may also be input. + * + * @see #SOURCE_CLASS_NONE + */ + public static final int SOURCE_GESTURE_SENSOR = 0x00400000 | SOURCE_CLASS_NONE; + /** * The input source is a joystick. * (It may also be a {@link #SOURCE_GAMEPAD}). @@ -787,6 +797,7 @@ public String toString() { appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad"); appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK, "joystick"); appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad"); + appendSourceDescriptionIfApplicable(description, SOURCE_GESTURE_SENSOR, "gesture"); description.append(" )\n"); final int numAxes = mMotionRanges.size(); diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 4a4799a13bd41..6ee95c79b70fd 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1293,6 +1293,9 @@ false + + false + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 9995fb651c256..bebf9ffd38fa9 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2037,6 +2037,9 @@ + + + diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index 06f57e2e9fa67..10dbaf42f64f1 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -2858,6 +2858,8 @@ void TouchInputMapper::configureParameters() { mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION; } else if (deviceTypeString == "pointer") { mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER; + } else if (deviceTypeString == "gesture") { + mParameters.deviceType = Parameters::DEVICE_TYPE_GESTURE_SENSOR; } else if (deviceTypeString != "default") { ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string()); } @@ -2906,6 +2908,9 @@ void TouchInputMapper::dumpParameters(String8& dump) { case Parameters::DEVICE_TYPE_POINTER: dump.append(INDENT4 "DeviceType: pointer\n"); break; + case Parameters::DEVICE_TYPE_GESTURE_SENSOR: + dump.append(INDENT4 "DeviceType: gesture\n"); + break; default: ALOG_ASSERT(false); } @@ -2959,6 +2964,9 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) { mSource = AINPUT_SOURCE_TOUCH_NAVIGATION; mDeviceMode = DEVICE_MODE_NAVIGATION; + } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_GESTURE_SENSOR) { + mSource = AINPUT_SOURCE_GESTURE_SENSOR; + mDeviceMode = DEVICE_MODE_UNSCALED; } else { mSource = AINPUT_SOURCE_TOUCHPAD; mDeviceMode = DEVICE_MODE_UNSCALED; diff --git a/services/input/InputReader.h b/services/input/InputReader.h index 7fe7dc1e5bf39..53472677c66d1 100644 --- a/services/input/InputReader.h +++ b/services/input/InputReader.h @@ -1219,6 +1219,7 @@ class TouchInputMapper : public InputMapper { DEVICE_TYPE_TOUCH_SCREEN, DEVICE_TYPE_TOUCH_PAD, DEVICE_TYPE_TOUCH_NAVIGATION, + DEVICE_TYPE_GESTURE_SENSOR, DEVICE_TYPE_POINTER, }; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 63d5108503b03..05e96fa5a3ab1 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -58,6 +58,7 @@ import com.android.server.content.ContentService; import com.android.server.display.DisplayManagerService; import com.android.server.dreams.DreamManagerService; +import com.android.server.gesture.GestureService; import com.android.server.input.InputManagerService; import com.android.server.net.NetworkPolicyManagerService; import com.android.server.net.NetworkStatsService; @@ -389,6 +390,7 @@ public void run() { LockSettingsService lockSettings = null; DreamManagerService dreamy = null; PieService pieService = null; + GestureService gestureService = null; // Bring up services needed for UI. if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { @@ -846,6 +848,17 @@ public void run() { } } + if (context.getResources().getBoolean( + com.android.internal.R.bool.config_enableGestureService)) { + try { + Slog.i(TAG, "Gesture Sensor Service"); + gestureService = new GestureService(context, inputManager); + ServiceManager.addService("gesture", gestureService); + } catch (Throwable e) { + Slog.e(TAG, "Failure starting Gesture Sensor Service", e); + } + } + try { Slog.i(TAG, "IdleMaintenanceService"); new IdleMaintenanceService(context, battery); @@ -952,6 +965,14 @@ public void run() { } } + if (gestureService != null) { + try { + gestureService.systemReady(); + } catch (Throwable e) { + reportWtf("making Gesture Sensor Service ready", e); + } + } + IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_APP_LAUNCH_FAILURE); filter.addAction(Intent.ACTION_APP_LAUNCH_FAILURE_RESET); diff --git a/services/java/com/android/server/gesture/GestureInputFilter.java b/services/java/com/android/server/gesture/GestureInputFilter.java new file mode 100644 index 0000000000000..d0341aabd421a --- /dev/null +++ b/services/java/com/android/server/gesture/GestureInputFilter.java @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2013 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.android.server.gesture; + +import android.content.Context; +import android.content.Intent; +import android.hardware.input.InputManager; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.SystemClock; +import android.os.UserHandle; +import android.util.Slog; +import android.view.Display; +import android.view.GestureDetector; +import android.view.GestureDetector.OnDoubleTapListener; +import android.view.IInputFilter; +import android.view.IInputFilterHost; +import android.view.InputDevice; +import android.view.InputEvent; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.OrientationEventListener; +import android.view.ViewConfiguration; +import android.view.WindowManager; + +import java.io.PrintWriter; + +/** + * A simple input filter that listens for gesture sensor events and converts + * them to input events to be injected into the input stream. + */ +public class GestureInputFilter implements IInputFilter, GestureDetector.OnGestureListener, OnDoubleTapListener { + + private static final String TAG = "GestureInputFilter"; + private static final boolean DEBUG = false; + + private IInputFilterHost mHost = null; + + private GestureDetector mGestureDetector; + private InputManager mInputManager; + private OrientationEventListener mOrientationListener; + private final int mScreenWidth, mScreenHeight; + private float mGesturePadWidth, mGesturePadHeight; + private int mTouchSlop, mOrientation; + private Context mContext; + + public GestureInputFilter(Context context) { + mInputManager = InputManager.getInstance(); + mContext = context; + for (int id : mInputManager.getInputDeviceIds()) { + InputDevice inputDevice = mInputManager.getInputDevice(id); + if ((inputDevice.getSources() & InputDevice.SOURCE_GESTURE_SENSOR) + == mInputManager.getInputDevice(id).getSources()) { + mGesturePadWidth = inputDevice.getMotionRange(MotionEvent.AXIS_X).getMax(); + mGesturePadHeight = inputDevice.getMotionRange(MotionEvent.AXIS_Y).getMax(); + break; + } + } + ViewConfiguration vc = ViewConfiguration.get(context); + mTouchSlop = vc.getScaledTouchSlop(); + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display display = wm.getDefaultDisplay(); + mScreenWidth = display.getWidth(); + mScreenHeight = display.getHeight(); + mGestureDetector = new GestureDetector(context, this); + mGestureDetector.setOnDoubleTapListener(this); + mOrientationListener = new OrientationEventListener(context) { + @Override + public void onOrientationChanged(int orientation) { + if (orientation == -1) { + return; + } + mOrientation = (orientation + 45) / 90 * 90; + } + }; + } + + /** + * Called to enqueue the input event for filtering. + * The event must be recycled after the input filter processed it. + * This method is guaranteed to be non-reentrant. + * + * @see InputFilter#filterInputEvent(InputEvent, int) + * @param event The input event to enqueue. + */ + // called by the input dispatcher thread + public void filterInputEvent(InputEvent event, int policyFlags) + throws RemoteException { + if (DEBUG) Slog.d(TAG, event.toString()); + + try { + if (event.getSource() != InputDevice.SOURCE_GESTURE_SENSOR + || !(event instanceof MotionEvent)) { + try { + mHost.sendInputEvent(event, policyFlags); + } catch (RemoteException e) { + /* ignore */ + } + return; + } + + MotionEvent motionEvent = (MotionEvent) event; + mGestureDetector.onTouchEvent(motionEvent); + } finally { + event.recycle(); + } + } + + // called by the input dispatcher thread + public void install(IInputFilterHost host) throws RemoteException { + if (DEBUG) { + Slog.d(TAG, "Gesture input filter installed."); + } + mHost = host; + mOrientationListener.enable(); + } + + // called by the input dispatcher thread + public void uninstall() throws RemoteException { + if (DEBUG) { + Slog.d(TAG, "Gesture input filter uninstalled."); + } + mHost = null; + mOrientationListener.disable(); + mContext = null; + } + + // should never be called + public IBinder asBinder() { + throw new UnsupportedOperationException(); + } + + // called by a Binder thread + public void dump(PrintWriter pw, String prefix) { + + } + + private boolean generateSwipe(MotionEvent e1, MotionEvent e2) { + switch (mOrientation) { + case 90: + Slog.d(TAG, "Adjusting motion for 90 degrees"); + e1.setLocation(e1.getY(), e1.getX()); + e2.setLocation(e2.getY(), e2.getX()); + break; + case 180: + Slog.d(TAG, "Adjusting motion for 180 degrees"); + e1.setLocation(mGesturePadWidth - e1.getX(), + mGesturePadHeight - e1.getY()); + e2.setLocation(mGesturePadWidth - e2.getX(), + mGesturePadHeight - e2.getY()); + break; + case 270: + Slog.d(TAG, "Adjusting motion for 270 degrees"); + e1.setLocation(mGesturePadHeight - e1.getY(), + e1.getX()); + e2.setLocation(mGesturePadHeight - e2.getY(), + e2.getX()); + break; + } + + float deltaX = Math.abs(e1.getX() - e2.getX()); + float deltaY = Math.abs(e1.getY() - e2.getY()); + + if (deltaX < mTouchSlop && deltaY < mTouchSlop) { + return false; + } + + if (deltaX > deltaY) { + e2.setLocation(e2.getX(), e1.getY()); + } else if (deltaY > deltaX) { + e2.setLocation(e1.getX(), e2.getY()); + } + + float scaleX = mScreenWidth / mGesturePadWidth; + float scaleY = mScreenHeight / mGesturePadHeight; + + float magnitudeX = deltaX * scaleX; + float magnitudeY = deltaY * scaleY; + + float origX = mScreenWidth / 2; + float origY = mScreenHeight / 2; + float endX = 0.0f; + float endY = 0.0f; + + if (e2.getY() > e1.getY()) { + if (DEBUG) Slog.d(TAG, "Detected down motion"); + // Ensure selection does not occur + endX = origX + mTouchSlop + 5; + endY = origY + magnitudeY; + } else if (e2.getY() < e1.getY()) { + if (DEBUG) Slog.d(TAG, "Detected up motion"); + endX = origX + mTouchSlop + 5; + endY = origY - magnitudeY; + } else if (e2.getX() > e1.getX()) { + if (DEBUG) Slog.d(TAG, "Detected left motion"); + endX = origX + magnitudeX; + endY = origY + mTouchSlop + 5; + } else if (e2.getX() < e1.getX()) { + if (DEBUG) Slog.d(TAG, "Detected right motion"); + endX = origX - magnitudeX; + endY = origY + mTouchSlop + 5; + } else { + return false; + } + + sendSwipe(origX, origY, endX, endY); + return true; + } + + private void sendSwipe(float x1, float y1, float x2, float y2) { + final long duration = 100; + long now = SystemClock.uptimeMillis(); + final long startTime = now; + final long endTime = startTime + duration; + sendMotionEvent(MotionEvent.ACTION_DOWN, now, x1, y1, 1.0f); + + while (now < endTime) { + long elapsedTime = now - startTime; + float alpha = (float) elapsedTime / duration; + sendMotionEvent(MotionEvent.ACTION_MOVE, now, + lerp(x1, x2, alpha), lerp(y1, y2, alpha), 1.0f); + now = SystemClock.uptimeMillis(); + } + sendMotionEvent(MotionEvent.ACTION_UP, now, x2, y2, 1.0f); + } + + private void sendMotionEvent(int action, long when, float x, float y, + float pressure) { + final float DEFAULT_SIZE = 1.0f; + final int DEFAULT_META_STATE = 0; + final float DEFAULT_PRECISION_X = 1.0f; + final float DEFAULT_PRECISION_Y = 1.0f; + final int DEFAULT_DEVICE_ID = 0; + final int DEFAULT_EDGE_FLAGS = 0; + + MotionEvent e = MotionEvent.obtain(when, when, action, x, y, pressure, + DEFAULT_SIZE, DEFAULT_META_STATE, DEFAULT_PRECISION_X, + DEFAULT_PRECISION_Y, DEFAULT_DEVICE_ID, DEFAULT_EDGE_FLAGS); + e.setSource(InputDevice.SOURCE_TOUCHSCREEN); + sendInputEvent(e); + } + + private void sendInputEvent(InputEvent event) { + mInputManager.injectInputEvent(event, + InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); + } + + private static final float lerp(float a, float b, float alpha) { + return (b - a) * alpha + a; + } + + @Override + public boolean onDown(MotionEvent e) { + return false; + } + + @Override + public void onShowPress(MotionEvent e) { + } + + @Override + public boolean onSingleTapUp(MotionEvent e) { + return false; + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, + float distanceY) { + return false; + } + + @Override + public void onLongPress(MotionEvent e) { + Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null); + mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF, + null, null, null, 0, null, null); + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, + float velocityY) { + return generateSwipe(e1, e2); + } + + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + return false; + } + + @Override + public boolean onDoubleTap(MotionEvent e) { + long now = SystemClock.uptimeMillis(); + sendInputEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, + KeyEvent.KEYCODE_CAMERA, 0, 0, + KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD)); + sendInputEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP,KeyEvent.KEYCODE_CAMERA, + 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD)); + return true; + } + + @Override + public boolean onDoubleTapEvent(MotionEvent e) { + return false; + } +} diff --git a/services/java/com/android/server/gesture/GestureService.java b/services/java/com/android/server/gesture/GestureService.java new file mode 100644 index 0000000000000..b163106984ccf --- /dev/null +++ b/services/java/com/android/server/gesture/GestureService.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2013 The CyanogenMod Project (Jens Doll) + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.android.server.gesture; + +import android.Manifest; +import android.content.Context; +import android.os.Binder; +import android.os.IBinder; +import android.os.RemoteException; +import android.service.gesture.IGestureService; +import android.util.Slog; + +import com.android.server.input.InputManagerService; + +/** + * A system service to track gesture sensor gestures. This service is + * responsible for creating input events from motion events generated by + * gesture sensor input hardware: + *

  • Installing an input filter to listen for gesture sensor events
  • + *
  • Generating input events to be injected into the input stream
  • + */ +public class GestureService extends IGestureService.Stub { + public static final String TAG = "GestureService"; + public static final boolean DEBUG = false; + + private Context mContext; + private InputManagerService mInputManager; + private GestureInputFilter mInputFilter; + + public GestureService(Context context, InputManagerService inputManager) { + mContext = context; + mInputManager = inputManager; + } + + // called by system server + public void systemReady() { + if (DEBUG) Slog.d(TAG, "Starting Gesture Sensor service"); + mInputFilter = new GestureInputFilter(mContext); + mInputManager.registerSecondaryInputFilter(mInputFilter); + } +} From dbb69170ddb51c9ad2f07733a9846d2867cf61b5 Mon Sep 17 00:00:00 2001 From: Ethan Chen Date: Mon, 21 Oct 2013 18:49:19 -0700 Subject: [PATCH 083/204] Hide InputDevice.SOURCE_GESTURE_SENSOR from API Change-Id: If009e9595fc593594b0e7764669996de137483a1 --- core/java/android/view/InputDevice.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java index 3acb9853b78c8..f6367107e34b4 100644 --- a/core/java/android/view/InputDevice.java +++ b/core/java/android/view/InputDevice.java @@ -226,6 +226,8 @@ public final class InputDevice implements Parcelable { * The same should apply for left, right, down swipes. Complex gestures may also be input. * * @see #SOURCE_CLASS_NONE + * + * @hide */ public static final int SOURCE_GESTURE_SENSOR = 0x00400000 | SOURCE_CLASS_NONE; From 952184b7ce2c0b3566027b4faf2abed5a20b9a16 Mon Sep 17 00:00:00 2001 From: Francesco Date: Sun, 20 Oct 2013 18:25:59 +0200 Subject: [PATCH 084/204] framework/base: IT translations Change-Id: I7713dd45668ee9adb489a86560cdcd4bd25ad95b --- packages/SystemUI/res/values-it/cm_strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/SystemUI/res/values-it/cm_strings.xml b/packages/SystemUI/res/values-it/cm_strings.xml index dbb5752dbe1f1..e4aa9c371c919 100644 --- a/packages/SystemUI/res/values-it/cm_strings.xml +++ b/packages/SystemUI/res/values-it/cm_strings.xml @@ -25,7 +25,7 @@ Timeout impostato a: %1$d %2$s GPS GPS OFF - Blocca telefono + Sospendi dispositivo Suoneria ON Suoneria OFF Vibrazione ON From 33012458dce5063516f114f618a104fa0b466565 Mon Sep 17 00:00:00 2001 From: Dan Pasanen Date: Tue, 22 Oct 2013 00:47:15 -0500 Subject: [PATCH 085/204] Quiet Hours: allow disabling of system sounds (1 of 2) * this include touch and lockscreen sounds Change-Id: I4b16be00ae24dafd0039834bf63f6df3ef918619 --- core/java/android/provider/Settings.java | 7 +++++ media/java/android/media/AudioManager.java | 29 +++++++++++++++++++ .../impl/keyguard/KeyguardViewMediator.java | 28 ++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 099593b38efd4..a508866e00090 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2983,6 +2983,12 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean */ public static final String QUIET_HOURS_HAPTIC = "quiet_hours_haptic"; + /** + * Whether to remove the system sounds during quiet hours. + * @hide + */ + public static final String QUIET_HOURS_SYSTEM = "quiet_hours_system"; + /** * Whether to remove the vibration from outgoing notifications during quiet hours. * @hide @@ -3374,6 +3380,7 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean QUIET_HOURS_START, QUIET_HOURS_END, QUIET_HOURS_MUTE, + QUIET_HOURS_SYSTEM, QUIET_HOURS_STILL, QUIET_HOURS_DIM, SYSTEM_PROFILES_ENABLED, diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 4213af1184bd8..3e011a6ca88ba 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -42,6 +42,7 @@ import android.view.KeyEvent; import android.view.VolumePanel; +import java.util.Calendar; import java.util.HashMap; /** @@ -1771,6 +1772,10 @@ public void playSoundEffect(int effectType) { return; } + if (inQuietHours()) { + return; + } + if (!querySoundEffectsEnabled()) { return; } @@ -1814,6 +1819,30 @@ public void playSoundEffect(int effectType, float volume) { } } + public boolean inQuietHours() { + boolean quietHoursEnabled = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.QUIET_HOURS_ENABLED, 0) != 0; + int quietHoursStart = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.QUIET_HOURS_START, 0); + int quietHoursEnd = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.QUIET_HOURS_END, 0); + boolean quietHoursSystem = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.QUIET_HOURS_SYSTEM, 0) != 0; + if (quietHoursEnabled && quietHoursSystem && (quietHoursStart != quietHoursEnd)) { + // Get the date in "quiet hours" format. + Calendar calendar = Calendar.getInstance(); + int minutes = calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE); + if (quietHoursEnd < quietHoursStart) { + // Starts at night, ends in the morning. + return (minutes > quietHoursStart) || (minutes < quietHoursEnd); + } else { + return (minutes > quietHoursStart) && (minutes < quietHoursEnd); + } + } + return false; + } + + /** * Settings has an in memory cache, so this is fast. */ diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java index 30f94eb28b6d7..3980934e78673 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java @@ -58,6 +58,7 @@ import com.android.internal.telephony.IccCardConstants; import com.android.internal.widget.LockPatternUtils; +import java.util.Calendar; /** * Mediates requests related to the keyguard. This includes queries about the @@ -1258,6 +1259,10 @@ private void playSounds(boolean locked) { return; } + if (inQuietHours()) { + return; + } + final ContentResolver cr = mContext.getContentResolver(); if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) { final int whichSound = locked @@ -1286,6 +1291,29 @@ private void updateActivityLockScreenState() { } } + public boolean inQuietHours() { + boolean quietHoursEnabled = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.QUIET_HOURS_ENABLED, 0) != 0; + int quietHoursStart = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.QUIET_HOURS_START, 0); + int quietHoursEnd = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.QUIET_HOURS_END, 0); + boolean quietHoursSystem = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.QUIET_HOURS_SYSTEM, 0) != 0; + if (quietHoursEnabled && quietHoursSystem && (quietHoursStart != quietHoursEnd)) { + // Get the date in "quiet hours" format. + Calendar calendar = Calendar.getInstance(); + int minutes = calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE); + if (quietHoursEnd < quietHoursStart) { + // Starts at night, ends in the morning. + return (minutes > quietHoursStart) || (minutes < quietHoursEnd); + } else { + return (minutes > quietHoursStart) && (minutes < quietHoursEnd); + } + } + return false; + } + /** * Handle message sent by {@link #showLocked}. * @see #SHOW From c6557ebd2a636b0f38a13dab893e99b34ef175f0 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Wed, 23 Oct 2013 02:15:56 +0100 Subject: [PATCH 086/204] PieInputFilter: Fix the check for the input device type input sources are composites with all the supported capabilities, not direct representations of the hardware. A touchscreen with gesture or stylus capabilities will be a TOUCHSCREEN|GESTURE, for example, and fail this check. Fix it. Change-Id: Ib3a5b27be9f461245c6d010e1a7f454e9284437f --- services/java/com/android/server/pie/PieInputFilter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/java/com/android/server/pie/PieInputFilter.java b/services/java/com/android/server/pie/PieInputFilter.java index 999cf7284921f..01af4c62c6b24 100644 --- a/services/java/com/android/server/pie/PieInputFilter.java +++ b/services/java/com/android/server/pie/PieInputFilter.java @@ -226,7 +226,8 @@ public void filterInputEvent(InputEvent event, int policyFlags) throws RemoteExc Trace.traceBegin(Trace.TRACE_TAG_INPUT, "filterInputEvent"); } try { - if (event.getSource() != InputDevice.SOURCE_TOUCHSCREEN + if (((event.getSource() & InputDevice.SOURCE_TOUCHSCREEN) + != InputDevice.SOURCE_TOUCHSCREEN) || !(event instanceof MotionEvent)) { sendInputEvent(event, policyFlags); return; From 36cc222c212340512188eda486e1b399726e40b9 Mon Sep 17 00:00:00 2001 From: Dan Pasanen Date: Tue, 22 Oct 2013 09:39:23 -0500 Subject: [PATCH 087/204] QuietHours: clean up and consolidate code Change-Id: Ib745ba91f800489518f1c7b5d2512ba946039696 --- .../internal/util/cm/QuietHoursUtils.java | 48 +++++++++++++++++ media/java/android/media/AudioManager.java | 28 ++-------- .../impl/keyguard/KeyguardViewMediator.java | 28 +--------- .../com/android/server/BatteryService.java | 23 ++------ .../server/NotificationManagerService.java | 54 ++++--------------- .../com/android/server/VibratorService.java | 30 ++--------- 6 files changed, 69 insertions(+), 142 deletions(-) create mode 100644 core/java/com/android/internal/util/cm/QuietHoursUtils.java diff --git a/core/java/com/android/internal/util/cm/QuietHoursUtils.java b/core/java/com/android/internal/util/cm/QuietHoursUtils.java new file mode 100644 index 0000000000000..bfb2085343d4b --- /dev/null +++ b/core/java/com/android/internal/util/cm/QuietHoursUtils.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.util.cm; + +import android.content.Context; +import android.provider.Settings; + +import java.util.Calendar; + +public class QuietHoursUtils { + public static boolean inQuietHours(Context context, String option) { + boolean quietHoursEnabled = Settings.System.getInt(context.getContentResolver(), + Settings.System.QUIET_HOURS_ENABLED, 0) != 0; + int quietHoursStart = Settings.System.getInt(context.getContentResolver(), + Settings.System.QUIET_HOURS_START, 0); + int quietHoursEnd = Settings.System.getInt(context.getContentResolver(), + Settings.System.QUIET_HOURS_END, 0); + boolean quietHoursOption = Settings.System.getInt(context.getContentResolver(), + option, 0) != 0; + if (quietHoursEnabled && quietHoursOption && (quietHoursStart != quietHoursEnd)) { + // Get the date in "quiet hours" format. + Calendar calendar = Calendar.getInstance(); + int minutes = calendar.get(Calendar.HOUR_OF_DAY) * 60 + + calendar.get(Calendar.MINUTE); + if (quietHoursEnd < quietHoursStart) { + // Starts at night, ends in the morning. + return (minutes > quietHoursStart) || (minutes < quietHoursEnd); + } else { + return (minutes > quietHoursStart) && (minutes < quietHoursEnd); + } + } + return false; + } +} diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 3e011a6ca88ba..4eb7b39bf560b 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -42,9 +42,10 @@ import android.view.KeyEvent; import android.view.VolumePanel; -import java.util.Calendar; import java.util.HashMap; +import com.android.internal.util.cm.QuietHoursUtils; + /** * AudioManager provides access to volume and ringer mode control. *

    @@ -1772,7 +1773,7 @@ public void playSoundEffect(int effectType) { return; } - if (inQuietHours()) { + if (QuietHoursUtils.inQuietHours(mContext, Settings.System.QUIET_HOURS_SYSTEM)) { return; } @@ -1819,29 +1820,6 @@ public void playSoundEffect(int effectType, float volume) { } } - public boolean inQuietHours() { - boolean quietHoursEnabled = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.QUIET_HOURS_ENABLED, 0) != 0; - int quietHoursStart = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.QUIET_HOURS_START, 0); - int quietHoursEnd = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.QUIET_HOURS_END, 0); - boolean quietHoursSystem = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.QUIET_HOURS_SYSTEM, 0) != 0; - if (quietHoursEnabled && quietHoursSystem && (quietHoursStart != quietHoursEnd)) { - // Get the date in "quiet hours" format. - Calendar calendar = Calendar.getInstance(); - int minutes = calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE); - if (quietHoursEnd < quietHoursStart) { - // Starts at night, ends in the morning. - return (minutes > quietHoursStart) || (minutes < quietHoursEnd); - } else { - return (minutes > quietHoursStart) && (minutes < quietHoursEnd); - } - } - return false; - } - /** * Settings has an in memory cache, so this is fast. diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java index 3980934e78673..b9e590e5c6c10 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java @@ -56,10 +56,9 @@ import android.view.WindowManagerPolicy; import com.android.internal.telephony.IccCardConstants; +import com.android.internal.util.cm.QuietHoursUtils; import com.android.internal.widget.LockPatternUtils; -import java.util.Calendar; - /** * Mediates requests related to the keyguard. This includes queries about the * state of the keyguard, power management events that effect whether the keyguard @@ -1259,7 +1258,7 @@ private void playSounds(boolean locked) { return; } - if (inQuietHours()) { + if (QuietHoursUtils.inQuietHours(mContext, Settings.System.QUIET_HOURS_SYSTEM)) { return; } @@ -1291,29 +1290,6 @@ private void updateActivityLockScreenState() { } } - public boolean inQuietHours() { - boolean quietHoursEnabled = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.QUIET_HOURS_ENABLED, 0) != 0; - int quietHoursStart = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.QUIET_HOURS_START, 0); - int quietHoursEnd = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.QUIET_HOURS_END, 0); - boolean quietHoursSystem = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.QUIET_HOURS_SYSTEM, 0) != 0; - if (quietHoursEnabled && quietHoursSystem && (quietHoursStart != quietHoursEnd)) { - // Get the date in "quiet hours" format. - Calendar calendar = Calendar.getInstance(); - int minutes = calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE); - if (quietHoursEnd < quietHoursStart) { - // Starts at night, ends in the morning. - return (minutes > quietHoursStart) || (minutes < quietHoursEnd); - } else { - return (minutes > quietHoursStart) && (minutes < quietHoursEnd); - } - } - return false; - } - /** * Handle message sent by {@link #showLocked}. * @see #SHOW diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java index 954fe65cc0f06..2eb77177db8a6 100644 --- a/services/java/com/android/server/BatteryService.java +++ b/services/java/com/android/server/BatteryService.java @@ -19,6 +19,7 @@ import com.android.internal.app.IBatteryStats; import com.android.internal.os.DeviceDockBatteryHandler; import com.android.internal.os.IDeviceHandler; +import com.android.internal.util.cm.QuietHoursUtils; import com.android.server.am.BatteryStatsService; import android.app.ActivityManagerNative; @@ -52,7 +53,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; -import java.util.Calendar; + /** *

    BatteryService monitors the charging status, and charge level of the device @@ -165,7 +166,6 @@ public final class BatteryService extends Binder { private boolean mQuietHoursEnabled = false; private int mQuietHoursStart = 0; private int mQuietHoursEnd = 0; - private boolean mQuietHoursDim = true; public BatteryService(Context context, LightsService lights, IDeviceHandler deviceHandler) { mContext = context; @@ -794,7 +794,7 @@ public void updateLightsLocked() { if (!mLightEnabled) { // No lights if explicitly disabled mBatteryLight.turnOff(); - } else if (inQuietHours() && mQuietHoursDim) { + } else if (QuietHoursUtils.inQuietHours(mContext, Settings.System.QUIET_HOURS_DIM)) { if (mLedPulseEnabled && level < mLowBatteryWarningLevel && status != BatteryManager.BATTERY_STATUS_CHARGING) { // The battery is low, the device is not charging and the low battery pulse @@ -907,26 +907,9 @@ public void update() { Settings.System.QUIET_HOURS_START, 0, UserHandle.USER_CURRENT_OR_SELF); mQuietHoursEnd = Settings.System.getIntForUser(resolver, Settings.System.QUIET_HOURS_END, 0, UserHandle.USER_CURRENT_OR_SELF); - mQuietHoursDim = Settings.System.getIntForUser(resolver, - Settings.System.QUIET_HOURS_DIM, 0, UserHandle.USER_CURRENT_OR_SELF) != 0; updateLedPulse(); } } - private boolean inQuietHours() { - if (mQuietHoursEnabled && (mQuietHoursStart != mQuietHoursEnd)) { - // Get the date in "quiet hours" format. - Calendar calendar = Calendar.getInstance(); - int minutes = calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE); - if (mQuietHoursEnd < mQuietHoursStart) { - // Starts at night, ends in the morning. - return (minutes > mQuietHoursStart) || (minutes < mQuietHoursEnd); - } else { - return (minutes > mQuietHoursStart) && (minutes < mQuietHoursEnd); - } - } - return false; - } - } diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index d14985e5fe5ab..e98066dbafc41 100644 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -77,6 +77,8 @@ import android.view.accessibility.AccessibilityManager; import android.widget.Toast; +import com.android.internal.util.cm.QuietHoursUtils; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -180,18 +182,6 @@ public class NotificationManagerService extends INotificationManager.Stub private ArrayList mLights = new ArrayList(); private NotificationRecord mLedNotification; - private boolean mQuietHoursEnabled = false; - // Minutes from midnight when quiet hours begin. - private int mQuietHoursStart = 0; - // Minutes from midnight when quiet hours end. - private int mQuietHoursEnd = 0; - // Don't play sounds. - private boolean mQuietHoursMute = true; - // Don't vibrate. - private boolean mQuietHoursStill = true; - // Dim LED if hardware supports it. - private boolean mQuietHoursDim = true; - private final AppOpsManager mAppOps; // contains connections to all connected listeners, including app services @@ -1355,18 +1345,6 @@ void observe() { public void update() { ContentResolver resolver = mContext.getContentResolver(); - mQuietHoursEnabled = Settings.System.getIntForUser(resolver, - Settings.System.QUIET_HOURS_ENABLED, 0, UserHandle.USER_CURRENT_OR_SELF) != 0; - mQuietHoursStart = Settings.System.getIntForUser(resolver, - Settings.System.QUIET_HOURS_START, 0, UserHandle.USER_CURRENT_OR_SELF); - mQuietHoursEnd = Settings.System.getIntForUser(resolver, - Settings.System.QUIET_HOURS_END, 0, UserHandle.USER_CURRENT_OR_SELF); - mQuietHoursMute = Settings.System.getIntForUser(resolver, - Settings.System.QUIET_HOURS_MUTE, 0, UserHandle.USER_CURRENT_OR_SELF) != 0; - mQuietHoursStill = Settings.System.getIntForUser(resolver, - Settings.System.QUIET_HOURS_STILL, 0, UserHandle.USER_CURRENT_OR_SELF) != 0; - mQuietHoursDim = Settings.System.getIntForUser(resolver, - Settings.System.QUIET_HOURS_DIM, 0, UserHandle.USER_CURRENT_OR_SELF) != 0; } } @@ -1819,8 +1797,6 @@ public void enqueueNotificationInternal(String pkg, String basePkg, int callingU final boolean canInterrupt = (score >= SCORE_INTERRUPTION_THRESHOLD); synchronized (mNotificationList) { - final boolean inQuietHours = inQuietHours(); - final StatusBarNotification n = new StatusBarNotification( pkg, id, tag, callingUid, callingPid, score, notification, user); NotificationRecord r = new NotificationRecord(n); @@ -1935,14 +1911,16 @@ public void enqueueNotificationInternal(String pkg, String basePkg, int callingU Uri soundUri = null; - if (!(inQuietHours && mQuietHoursMute) && useDefaultSound) { + if (!(QuietHoursUtils.inQuietHours(mContext, Settings.System.QUIET_HOURS_MUTE)) + && useDefaultSound) { soundUri = Settings.System.DEFAULT_NOTIFICATION_URI; // check to see if the default notification sound is silent ContentResolver resolver = mContext.getContentResolver(); hasValidSound = Settings.System.getString(resolver, Settings.System.NOTIFICATION_SOUND) != null; - } else if (!(inQuietHours && mQuietHoursMute) && notification.sound != null) { + } else if (!(QuietHoursUtils.inQuietHours(mContext, + Settings.System.QUIET_HOURS_MUTE)) && notification.sound != null) { soundUri = notification.sound; hasValidSound = (soundUri != null); } @@ -1995,7 +1973,7 @@ && shouldConvertSoundToVibration() final boolean useDefaultVibrate = (notification.defaults & Notification.DEFAULT_VIBRATE) != 0; - if (!(inQuietHours && mQuietHoursStill) + if (!(QuietHoursUtils.inQuietHours(mContext, Settings.System.QUIET_HOURS_MUTE)) && (useDefaultVibrate || convertSoundToVibration || hasCustomVibrate) && !(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT)) { mVibrateNotification = r; @@ -2066,21 +2044,6 @@ private boolean canVibrateDuringAlertsDisabled() { 0, UserHandle.USER_CURRENT_OR_SELF) != 0; } - private boolean inQuietHours() { - if (mQuietHoursEnabled && (mQuietHoursStart != mQuietHoursEnd)) { - // Get the date in "quiet hours" format. - Calendar calendar = Calendar.getInstance(); - int minutes = calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE); - if (mQuietHoursEnd < mQuietHoursStart) { - // Starts at night, ends in the morning. - return (minutes > mQuietHoursStart) || (minutes < mQuietHoursEnd); - } else { - return (minutes > mQuietHoursStart) && (minutes < mQuietHoursEnd); - } - } - return false; - } - private void sendAccessibilityEvent(Notification notification, CharSequence packageName) { AccessibilityManager manager = AccessibilityManager.getInstance(mContext); if (!manager.isEnabled()) { @@ -2354,7 +2317,8 @@ private void updateLightsLocked() { // Don't flash while we are in a call, screen is on or we are // in quiet hours with light dimmed if (mLedNotification == null || mInCall - || (mScreenOn && !mDreaming) || (inQuietHours() && mQuietHoursDim)) { + || (mScreenOn && !mDreaming) + || (QuietHoursUtils.inQuietHours(mContext, Settings.System.QUIET_HOURS_DIM))) { mNotificationLight.turnOff(); } else if (mNotificationPulseEnabled) { final Notification ledno = mLedNotification.sbn.getNotification(); diff --git a/services/java/com/android/server/VibratorService.java b/services/java/com/android/server/VibratorService.java index 08a3333c7dd80..e4a946340c3bc 100644 --- a/services/java/com/android/server/VibratorService.java +++ b/services/java/com/android/server/VibratorService.java @@ -43,9 +43,9 @@ import com.android.internal.app.IAppOpsService; import com.android.internal.app.IBatteryStats; +import com.android.internal.util.cm.QuietHoursUtils; import java.util.ArrayList; -import java.util.Calendar; import java.util.LinkedList; import java.util.ListIterator; @@ -179,29 +179,6 @@ public boolean hasVibrator() { return doVibratorExists(); } - private boolean inQuietHours() { - boolean quietHoursEnabled = Settings.System.getIntForUser(mContext.getContentResolver(), - Settings.System.QUIET_HOURS_ENABLED, 0, UserHandle.USER_CURRENT_OR_SELF) != 0; - int quietHoursStart = Settings.System.getIntForUser(mContext.getContentResolver(), - Settings.System.QUIET_HOURS_START, 0, UserHandle.USER_CURRENT_OR_SELF); - int quietHoursEnd = Settings.System.getIntForUser(mContext.getContentResolver(), - Settings.System.QUIET_HOURS_END, 0, UserHandle.USER_CURRENT_OR_SELF); - boolean quietHoursHaptic = Settings.System.getIntForUser(mContext.getContentResolver(), - Settings.System.QUIET_HOURS_HAPTIC, 0, UserHandle.USER_CURRENT_OR_SELF) != 0; - if (quietHoursEnabled && quietHoursHaptic && (quietHoursStart != quietHoursEnd)) { - // Get the date in "quiet hours" format. - Calendar calendar = Calendar.getInstance(); - int minutes = calendar.get(Calendar.HOUR_OF_DAY) * 60 + calendar.get(Calendar.MINUTE); - if (quietHoursEnd < quietHoursStart) { - // Starts at night, ends in the morning. - return (minutes > quietHoursStart) || (minutes < quietHoursEnd); - } else { - return (minutes > quietHoursStart) && (minutes < quietHoursEnd); - } - } - return false; - } - private void verifyIncomingUid(int uid) { if (uid == Binder.getCallingUid()) { return; @@ -223,7 +200,8 @@ public void vibrate(int uid, String packageName, long milliseconds, IBinder toke // timeout of 0 or negative. This will ensure that a vibration has // either a timeout of > 0 or a non-null pattern. if (milliseconds <= 0 || (mCurrentVibration != null - && mCurrentVibration.hasLongerTimeout(milliseconds)) || inQuietHours()) { + && mCurrentVibration.hasLongerTimeout(milliseconds)) + || QuietHoursUtils.inQuietHours(mContext, Settings.System.QUIET_HOURS_HAPTIC)) { // Ignore this vibration since the current vibration will play for // longer than milliseconds. return; @@ -260,7 +238,7 @@ public void vibratePattern(int uid, String packageName, long[] pattern, int repe != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Requires VIBRATE permission"); } - if (inQuietHours()) { + if (QuietHoursUtils.inQuietHours(mContext, Settings.System.QUIET_HOURS_HAPTIC)) { return; } verifyIncomingUid(uid); From 27317047015924998c4ccfb2903c3755a137431c Mon Sep 17 00:00:00 2001 From: Ondrej Zima Date: Wed, 23 Oct 2013 23:55:43 +0200 Subject: [PATCH 088/204] framework/base: CS translation - AOSP: added new keygurad messages, locksreen messages, pinpuk attempts, USSD/SS/DIAL request messages Change-Id: Ife18ca6099f9eb9d165ad4b047c6db7022da3775 --- core/res/res/values-cs/cm_strings.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/core/res/res/values-cs/cm_strings.xml b/core/res/res/values-cs/cm_strings.xml index b3775b65f7559..6db3ac6b1b1f7 100644 --- a/core/res/res/values-cs/cm_strings.xml +++ b/core/res/res/values-cs/cm_strings.xml @@ -14,7 +14,22 @@ limitations under the License. --> + Neúspěšné. Povolte zámek SIM/RUIM. + Nesprávný kód PUK! + Akce PIN se nezdařila! + Akce PUK se nezdařila! + Kód přijat! + \nZbývá pokusů: + Neplatná karta. + Karta SIM je neplatná. + Karta SIM/RUIM je zamčená Dotykem nastavit + Požadavek USSD je změněn na požadavek DIAL. + Požadavek USSD je změněn na požadavek SS. + Požadavek USSD je změněn na nový požadavek USSD. + Požadavek SS je změněn na požadavek DIAL. + Požadavek SS je změněn na požadavek USSD. + Požadavek SS je změněn na nový požadavek SS. Výchozí Práce From 115150df8947a91e48f62b3dd4e446763fa288cd Mon Sep 17 00:00:00 2001 From: Ethan Chen Date: Wed, 23 Oct 2013 19:32:54 -0700 Subject: [PATCH 089/204] NetworkController: Hide signal strength icon when no SIM icon is shown Change-Id: I5c4b43bba1469e14474d20a3627eafa597459e6e --- .../systemui/statusbar/policy/MSimNetworkController.java | 4 ++++ .../android/systemui/statusbar/policy/NetworkController.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java index 4aebaa165a880..f7f2d77a46fd7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java @@ -986,7 +986,11 @@ else if (!mMSimDataConnected[subscription] && !mWifiConnected && !mBluetoothTeth } else if (mPhone.isNetworkRoaming(subscription)) { mMSimDataTypeIconId[subscription] = R.drawable.stat_sys_data_connected_roam; } + } else if (mMSimState[subscription] == IccCardConstants.State.ABSENT) { + mMSimPhoneSignalIconId[subscription] = mMSimDataSignalIconId[subscription] + = mMSimDataTypeIconId[subscription] = 0; } + if (DEBUG) { Slog.d(TAG, "refreshViews connected={" + (mWifiConnected?" wifi":"") diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 1c88fe691f744..479dca6e0147f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -1271,6 +1271,10 @@ void refreshViews() { mDataTypeIconId = R.drawable.stat_sys_data_connected_roam; mQSDataTypeIconId = R.drawable.ic_qs_signal_r; } + } else if (mSimState == IccCardConstants.State.ABSENT) { + // look again; your radios are now sim cards + mPhoneSignalIconId = mDataSignalIconId = mDataTypeIconId = mQSDataTypeIconId = 0; + mQSPhoneSignalIconId = 0; } if (DEBUG) { From a2e75c2760b255d7029b340e72c39605aadd8bbf Mon Sep 17 00:00:00 2001 From: trulyliu Date: Thu, 24 Oct 2013 12:52:11 +0800 Subject: [PATCH 090/204] TD_SCDMA signal strength support Change-Id: I0a86eba7c51834054400233044610fa08e7f7fcd --- telephony/java/android/telephony/SignalStrength.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java index 7e85cb3c4d5fa..fad5029562e39 100644 --- a/telephony/java/android/telephony/SignalStrength.java +++ b/telephony/java/android/telephony/SignalStrength.java @@ -512,7 +512,7 @@ public int getLevel() { boolean lteChecks = (getLteRsrp() == INVALID && getLteRsrq() == INVALID && getLteRssnr() == INVALID && getLteSignalStrenght() == 99); boolean oldRil = needsOldRilFeature("signalstrength"); level = getLteLevel(); - if ((level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN && getGsmAsuLevel() != 99 && lteChecks) || oldRil) { + if ((level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN && (getGsmAsuLevel() != 99 || getTdScdmaAsuLevel() != 255) && lteChecks) || oldRil) { level = getTdScdmaLevel(); if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { level = getGsmLevel(); @@ -546,7 +546,7 @@ public int getAsuLevel() { if (isGsm) { boolean oldRil = needsOldRilFeature("signalstrength"); boolean lteChecks = (getLteRsrp() == INVALID && getLteRsrq() == INVALID && getLteRssnr() == INVALID && getLteSignalStrenght() == 99); - if ((getLteLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN && getGsmAsuLevel() != 99 && lteChecks) || oldRil) { + if ((getLteLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN && (getGsmAsuLevel() != 99 || getTdScdmaAsuLevel() != 255) && lteChecks) || oldRil) { if (getTdScdmaLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { asuLevel = getGsmAsuLevel(); } else { @@ -584,7 +584,7 @@ public int getDbm() { if(isGsm()) { boolean oldRil = needsOldRilFeature("signalstrength"); boolean lteChecks = (getLteRsrp() == INVALID && getLteRsrq() == INVALID && getLteRssnr() == INVALID && getLteSignalStrenght() == 99); - if ((getLteLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN && getGsmAsuLevel() != 99 && lteChecks) || oldRil) { + if ((getLteLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN && (getGsmAsuLevel() != 99 || getTdScdmaAsuLevel() != 255) && lteChecks) || oldRil) { if (getTdScdmaLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { dBm = getGsmDbm(); } else { From af64bc66a151287e137c91e3cd09d607386f6613 Mon Sep 17 00:00:00 2001 From: Pawit Pornkitprasan Date: Thu, 24 Oct 2013 16:16:30 +0700 Subject: [PATCH 091/204] telephony: disable the use of SMS_EXPECT_MORE by default (1/2) CodeAurora added the use of the RIL_REQUEST_SEND_SMS_EXPECT_MORE API which is not supported by every RIL. Disabled it by default to reflect AOSP behavior and added a flag to enable it. Change-Id: I837c161bbca3960e7458ea049f896218d5e60a63 --- core/res/res/values/config.xml | 7 +++++++ core/res/res/values/symbols.xml | 3 +++ 2 files changed, 10 insertions(+) diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index d4d1dbbe36b9e..eab7a5b739a73 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1309,4 +1309,11 @@ false + + + false diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index b8a08c964130b..4cbff9d29a6aa 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2086,4 +2086,7 @@ + + + From fc96fb121e86f6f059e7d9660f386aef4dd3ac57 Mon Sep 17 00:00:00 2001 From: Tamas Toth Date: Thu, 24 Oct 2013 09:55:36 +0200 Subject: [PATCH 092/204] core: HU translation Change-Id: I91d17dd960fc369cb415446d09c4a0b2dc38596d --- core/res/res/values-hu/cm_strings.xml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/core/res/res/values-hu/cm_strings.xml b/core/res/res/values-hu/cm_strings.xml index 7cae3904636d7..2a2306a865cee 100644 --- a/core/res/res/values-hu/cm_strings.xml +++ b/core/res/res/values-hu/cm_strings.xml @@ -71,4 +71,21 @@ MMAC Váltás a biztonságos és az engedélyező MMAC mód között. Nincs eltávolítható memóriakártya\u2026 + Sikertelen. Engedélyezze a SIM/RUIM zárat. + Helytelen PUK kód. + PIN művelet sikertelen! + PUK művelet sikertelen! + Kód elfogadva! + \nHátralévő kisérletek: + Érvénytelen kártya. + Érvénytelen SIM kártya. + SIM/RUIM Perso záras + USSD kérés módosítva DIAL kérésre. + USSD kérés módosítva SS kérésre. + USSD kérés módosítva új USSD kérésre. + SS kérés módosítva DIAL kérésre. + SS kérés módosítva USSD kérésre. + SS kérés módosítva új SS kérésre. + SUB:%d : %s. + %s, %s From b1b9e7c7a61364ff591830a184189c31f0d223e4 Mon Sep 17 00:00:00 2001 From: Lorenzo M Date: Thu, 24 Oct 2013 23:22:39 +0200 Subject: [PATCH 093/204] frameworks_base: ES translations Change-Id: I252b7b8bfe8f6cf38bace2abee36aeaaef82b5d7 --- core/res/res/values-es/cm_strings.xml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/core/res/res/values-es/cm_strings.xml b/core/res/res/values-es/cm_strings.xml index b84eb0a028f94..f77e607a9747f 100644 --- a/core/res/res/values-es/cm_strings.xml +++ b/core/res/res/values-es/cm_strings.xml @@ -17,6 +17,23 @@ Conversaciones No hay medios extraíbles\u2026 + No realizado. Habilita antes el bloqueo de SIM/RUIM. + ¡Código PUK incorrecto! + ¡Falló la operación de PIN! + ¡Falló la operación de PUK! + ¡Código aceptado! + \nIntentos restantes: + Tarjeta inválida. + La tarjeta SIM no es válida. + SIM/RUIM tiene bloqueo personalizado + Solicitud USSD es modificada a solicitud DIAL. + Solicitud USSD es modificada a solicitud SS. + Solicitud USSD es modificada a nueva solicitud USSD. + Solicitud SS es modificada a solicitud DIAL. + Solicitud SS es modificada a solicitud USSD. + Solicitud SS es modificada a nueva solicitud SS. + SUS:%d : %s. + %s, %s Predeterminado Trabajo Casa From 8bc226c61f18e4398990a0843adbc32697025c2b Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Thu, 24 Oct 2013 17:47:16 -0700 Subject: [PATCH 094/204] ISms.aidl: Add callingPkg to sendTextWithPriority. Needed for Voice+ and SecureSMS, due to breakage caused by QCOM merge Change-Id: I1871bc9e3f644b7b82f7da18f404921c237ec55c --- telephony/java/com/android/internal/telephony/ISms.aidl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl index a94bcc9728e19..8d18287fda3b8 100644 --- a/telephony/java/com/android/internal/telephony/ISms.aidl +++ b/telephony/java/com/android/internal/telephony/ISms.aidl @@ -145,7 +145,7 @@ interface ISms { * raw pdu of the status report is in the extended data ("pdu"). * @param priority Priority level of the message */ - void sendTextWithPriority(in String destAddr, in String scAddr, in String text, + void sendTextWithPriority(String callingPkg, in String destAddr, in String scAddr, in String text, in PendingIntent sentIntent, in PendingIntent deliveryIntent, in int priority); From 858d67d29f30a0256014d7a318b3586db10d0bb0 Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Sun, 15 Sep 2013 01:39:41 -0700 Subject: [PATCH 095/204] Remote display framework support. Any app can use the remote display APIs to mirror to another device... This can be used to implement AirPlay, Chromecast, or even screen recording. Change-Id: I6f45b393afb2f9d438d4aa548e8149946741c928 --- Android.mk | 2 + .../hardware/display/DisplayManager.java | 15 + .../display/DisplayManagerGlobal.java | 10 + .../hardware/display/IDisplayDevice.aidl | 24 ++ .../hardware/display/IDisplayManager.aidl | 4 + .../display/IRemoteDisplayAdapter.aidl | 56 ++++ .../android/hardware/display/WifiDisplay.java | 10 + .../policy/impl/PhoneWindowManager.java | 29 ++ .../server/display/DisplayManagerService.java | 34 ++ .../server/display/RemoteDisplayAdapter.java | 313 ++++++++++++++++++ 10 files changed, 497 insertions(+) create mode 100644 core/java/android/hardware/display/IDisplayDevice.aidl create mode 100644 core/java/android/hardware/display/IRemoteDisplayAdapter.aidl create mode 100644 services/java/com/android/server/display/RemoteDisplayAdapter.java diff --git a/Android.mk b/Android.mk index 33384b2674ff1..91e4fc2fea668 100644 --- a/Android.mk +++ b/Android.mk @@ -122,8 +122,10 @@ LOCAL_SRC_FILES += \ core/java/android/content/pm/IPackageStatsObserver.aidl \ core/java/android/database/IContentObserver.aidl \ core/java/android/hardware/ISerialManager.aidl \ + core/java/android/hardware/display/IDisplayDevice.aidl \ core/java/android/hardware/display/IDisplayManager.aidl \ core/java/android/hardware/display/IDisplayManagerCallback.aidl \ + core/java/android/hardware/display/IRemoteDisplayAdapter.aidl \ core/java/android/hardware/input/IInputManager.aidl \ core/java/android/hardware/input/IInputDevicesChangedListener.aidl \ core/java/android/hardware/location/IGeofenceHardware.aidl \ diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 0a7a2e71b770a..1f315becea3a9 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 The Android Open Source Project + * Copyright (C) 2012 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +19,7 @@ import android.content.Context; import android.os.Handler; +import android.os.RemoteException; import android.util.SparseArray; import android.view.Display; @@ -64,6 +66,12 @@ public final class DisplayManager { public static final String EXTRA_WIFI_DISPLAY_STATUS = "android.hardware.display.extra.WIFI_DISPLAY_STATUS"; + public static final String ACTION_REMOTE_DISPLAY_STATUS_CHANGED = + "android.hardware.display.action.REMOTE_DISPLAY_STATUS_CHANGED"; + + public static final String EXTRA_REMOTE_DISPLAY_STATUS = + "android.hardware.display.extra.REMOTE_DISPLAY_STATUS"; + /** * Display category: Presentation displays. *

    @@ -274,6 +282,13 @@ public WifiDisplayStatus getWifiDisplayStatus() { return mGlobal.getWifiDisplayStatus(); } + /** + * @hide + */ + public IRemoteDisplayAdapter getRemoteDisplayAdapter() { + return mGlobal.getRemoteDisplayAdapter(); + } + /** * Listens for changes in available display devices. */ diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java index a8586814af6ed..5128a737125b3 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 The Android Open Source Project + * Copyright (C) 2013 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -315,6 +316,15 @@ public WifiDisplayStatus getWifiDisplayStatus() { } } + public IRemoteDisplayAdapter getRemoteDisplayAdapter() { + try { + return mDm.getRemoteDisplayAdapter(); + } + catch (RemoteException e) { + return null; + } + } + private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub { @Override public void onDisplayEvent(int displayId, int event) { diff --git a/core/java/android/hardware/display/IDisplayDevice.aidl b/core/java/android/hardware/display/IDisplayDevice.aidl new file mode 100644 index 0000000000000..a07165db8d49d --- /dev/null +++ b/core/java/android/hardware/display/IDisplayDevice.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2013 The CyanogenMod 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.hardware.display; + +import android.view.Surface; + +interface IDisplayDevice { + Surface createDisplaySurface(); + oneway void stop(); +} diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl index 79aad78d53941..d523824dd1e88 100644 --- a/core/java/android/hardware/display/IDisplayManager.aidl +++ b/core/java/android/hardware/display/IDisplayManager.aidl @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 The Android Open Source Project + * Copyright (C) 2013 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +21,7 @@ import android.hardware.display.IDisplayManagerCallback; import android.hardware.display.WifiDisplay; import android.hardware.display.WifiDisplayStatus; import android.view.DisplayInfo; +import android.hardware.display.IRemoteDisplayAdapter; /** @hide */ interface IDisplayManager { @@ -46,4 +48,6 @@ interface IDisplayManager { // No permissions required. WifiDisplayStatus getWifiDisplayStatus(); + + IRemoteDisplayAdapter getRemoteDisplayAdapter(); } diff --git a/core/java/android/hardware/display/IRemoteDisplayAdapter.aidl b/core/java/android/hardware/display/IRemoteDisplayAdapter.aidl new file mode 100644 index 0000000000000..b945f654e6879 --- /dev/null +++ b/core/java/android/hardware/display/IRemoteDisplayAdapter.aidl @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2013 The CyanogenMod 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.hardware.display; + +import android.hardware.display.WifiDisplayStatus; +import android.hardware.display.IDisplayDevice; + +interface IRemoteDisplayAdapter { + // No permissions required. + oneway void scanRemoteDisplays(); + + // Requires CONFIGURE_WIFI_DISPLAY permission to connect to an unknown device. + // No permissions required to connect to a known device. + oneway void connectRemoteDisplay(String address); + + // No permissions required. + oneway void disconnectRemoteDisplay(); + + // Requires CONFIGURE_WIFI_DISPLAY permission. + oneway void forgetRemoteDisplay(String address); + + // Requires CONFIGURE_WIFI_DISPLAY permission. + oneway void renameRemoteDisplay(String address, String alias); + + // No permissions required. + /** + /* @hide + */ + WifiDisplayStatus getRemoteDisplayStatus(); + + oneway void registerDisplayDevice( + IDisplayDevice device, + String name, + int width, + int height, + float refreshRate, + int flags, + String address, + boolean hidden); + + oneway void unregisterDisplayDevice(IDisplayDevice device); +} diff --git a/core/java/android/hardware/display/WifiDisplay.java b/core/java/android/hardware/display/WifiDisplay.java index 2fd52b8f4e7a6..a18538ae01a9b 100644 --- a/core/java/android/hardware/display/WifiDisplay.java +++ b/core/java/android/hardware/display/WifiDisplay.java @@ -33,6 +33,7 @@ public final class WifiDisplay implements Parcelable { private final String mDeviceAddress; private final String mDeviceName; private final String mDeviceAlias; + private final boolean mHidden; public static final WifiDisplay[] EMPTY_ARRAY = new WifiDisplay[0]; @@ -50,6 +51,10 @@ public WifiDisplay[] newArray(int size) { }; public WifiDisplay(String deviceAddress, String deviceName, String deviceAlias) { + this(deviceAddress, deviceName, deviceAlias, false); + } + + public WifiDisplay(String deviceAddress, String deviceName, String deviceAlias, boolean hidden) { if (deviceAddress == null) { throw new IllegalArgumentException("deviceAddress must not be null"); } @@ -60,6 +65,7 @@ public WifiDisplay(String deviceAddress, String deviceName, String deviceAlias) mDeviceAddress = deviceAddress; mDeviceName = deviceName; mDeviceAlias = deviceAlias; + mHidden = hidden; } /** @@ -95,6 +101,10 @@ public String getFriendlyDisplayName() { return mDeviceAlias != null ? mDeviceAlias : mDeviceName; } + public boolean isHidden() { + return mHidden; + } + @Override public boolean equals(Object o) { return o instanceof WifiDisplay && equals((WifiDisplay)o); diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index d4a4db9473544..25f22f3db7bde 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -813,6 +813,19 @@ private void interceptScreenshotChord() { } } + private void interceptScreencastChord() { + if (mVolumeUpKeyTriggered && mPowerKeyTriggered && !mVolumeDownKeyTriggered) { + final long now = SystemClock.uptimeMillis(); + if (now <= mVolumeUpKeyTime + ACTION_CHORD_DEBOUNCE_DELAY_MILLIS + && now <= mPowerKeyTime + ACTION_CHORD_DEBOUNCE_DELAY_MILLIS) { + mVolumeUpKeyConsumedByChord = true; + cancelPendingPowerKeyAction(); + + mHandler.postDelayed(mScreencastRunnable, getScreenshotChordLongPressDelay()); + } + } + } + private long getScreenshotChordLongPressDelay() { if (mKeyguardMediator.isShowing()) { // Double the time it takes to take a screenshot from the keyguard @@ -826,6 +839,10 @@ private void cancelPendingScreenshotChordAction() { mHandler.removeCallbacks(mScreenshotRunnable); } + private void cancelPendingScreencastChordAction() { + mHandler.removeCallbacks(mScreencastRunnable); + } + private void interceptRingerChord() { if (mVolumeDownKeyTriggered && !mPowerKeyTriggered && mVolumeUpKeyTriggered) { final long now = SystemClock.uptimeMillis(); @@ -886,6 +903,14 @@ public void run() { } }; + private final Runnable mScreencastRunnable = new Runnable() { + @Override + public void run() { + Intent screencastIntent = new Intent("com.cyanogenmod.ACTION_START_SCREENCAST"); + mContext.sendBroadcastAsUser(screencastIntent, UserHandle.CURRENT_OR_SELF); + } + }; + private final Runnable mRingerChordLongPress = new Runnable() { public void run() { // Do the switch @@ -4242,6 +4267,7 @@ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean i mVolumeDownKeyTime = event.getDownTime(); mVolumeDownKeyConsumedByChord = false; cancelPendingPowerKeyAction(); + cancelPendingScreencastChordAction(); interceptScreenshotChord(); interceptRingerChord(); } @@ -4249,6 +4275,7 @@ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean i mVolumeDownKeyTriggered = false; cancelPendingScreenshotChordAction(); cancelPendingRingerChordAction(); + cancelPendingScreencastChordAction(); } } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { if (down) { @@ -4260,11 +4287,13 @@ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean i cancelPendingPowerKeyAction(); cancelPendingScreenshotChordAction(); interceptRingerChord(); + interceptScreencastChord(); } } else { mVolumeUpKeyTriggered = false; cancelPendingScreenshotChordAction(); cancelPendingRingerChordAction(); + cancelPendingScreencastChordAction(); } } if (down) { diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java index 17b066272262a..741ea252787ca 100644 --- a/services/java/com/android/server/display/DisplayManagerService.java +++ b/services/java/com/android/server/display/DisplayManagerService.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 The Android Open Source Project + * Copyright (C) 2012 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +25,7 @@ import android.hardware.display.DisplayManagerGlobal; import android.hardware.display.IDisplayManager; import android.hardware.display.IDisplayManagerCallback; +import android.hardware.display.IRemoteDisplayAdapter; import android.hardware.display.WifiDisplayStatus; import android.os.Binder; import android.os.Handler; @@ -170,6 +172,8 @@ public final class DisplayManagerService extends IDisplayManager.Stub { // The Wifi display adapter, or null if not registered. private WifiDisplayAdapter mWifiDisplayAdapter; + private RemoteDisplayAdapter mRemoteDisplayAdapter; + // Viewports of the default display and the display that should receive touch // input from an external source. Used by the input system. private final DisplayViewport mDefaultViewport = new DisplayViewport(); @@ -582,11 +586,30 @@ private void registerDefaultDisplayAdapter() { } } + public void scanRemoteDisplays() { + final long token = Binder.clearCallingIdentity(); + try { + synchronized (mSyncRoot) { + if (mRemoteDisplayAdapter != null) { + mRemoteDisplayAdapter.mStub.scanRemoteDisplays(); + } + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override + public IRemoteDisplayAdapter getRemoteDisplayAdapter() { + return mRemoteDisplayAdapter.mStub; + } + private void registerAdditionalDisplayAdapters() { synchronized (mSyncRoot) { if (shouldRegisterNonEssentialDisplayAdaptersLocked()) { registerOverlayDisplayAdapterLocked(); registerWifiDisplayAdapterLocked(); + registerRemoteDisplayAdapterLocked(); } } } @@ -607,6 +630,17 @@ private void registerWifiDisplayAdapterLocked() { } } + private void registerRemoteDisplayAdapterLocked() { + if (mContext.getResources().getBoolean( + com.android.internal.R.bool.config_enableWifiDisplay) + || SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) { + mRemoteDisplayAdapter = new RemoteDisplayAdapter( + mSyncRoot, mContext, mHandler, mDisplayAdapterListener, + mPersistentDataStore); + registerDisplayAdapterLocked(mRemoteDisplayAdapter); + } + } + private boolean shouldRegisterNonEssentialDisplayAdaptersLocked() { // In safe mode, we disable non-essential display adapters to give the user // an opportunity to fix broken settings or other problems that might affect diff --git a/services/java/com/android/server/display/RemoteDisplayAdapter.java b/services/java/com/android/server/display/RemoteDisplayAdapter.java new file mode 100644 index 0000000000000..cb997ba93a37c --- /dev/null +++ b/services/java/com/android/server/display/RemoteDisplayAdapter.java @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2012 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.display; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.hardware.display.DisplayManager; +import android.hardware.display.IDisplayDevice; +import android.hardware.display.IRemoteDisplayAdapter; +import android.hardware.display.WifiDisplay; +import android.hardware.display.WifiDisplayStatus; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.UserHandle; +import android.util.Log; +import android.view.Display; +import android.view.Surface; +import android.view.SurfaceControl; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; + +public class RemoteDisplayAdapter extends DisplayAdapter { + private static class RemoteDisplay { + RemoteDisplayDevice remoteDisplayDevice; + DisplayDeviceInfo info; + IDisplayDevice displayDevice; + boolean hidden; + } + + private static final String TAG = "RemoteDisplayAdapter"; + private static final String SCAN = "com.cyanogenmod.server.display.SCAN"; + private static final String STOP_SCAN = "com.cyanogenmod.server.display.STOP_SCAN"; + + private Hashtable mDevices = new Hashtable(); + private boolean mScanning; + private Handler mHandler; + private RemoteDisplay mActiveDisplay; + Stub mStub = new Stub(); + + class Stub extends IRemoteDisplayAdapter.Stub { + public void registerDisplayDevice(IDisplayDevice displayDevice, String name, int width, + int height, float refreshRate, int flags, String address, boolean hidden) { + synchronized (getSyncRoot()) { + RemoteDisplay display = new RemoteDisplay(); + display.hidden = hidden; + display.info = new DisplayDeviceInfo(); + display.displayDevice = displayDevice; + mDevices.put(address, display); + DisplayDeviceInfo info = display.info; + info.name = name; + info.width = width; + info.height = height; + info.refreshRate = refreshRate; + info.flags = flags; + info.type = Display.TYPE_UNKNOWN; + info.address = address; + info.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; + info.setAssumedDensityForExternalDisplay(width, height); + handleSendStatusChangeBroadcast(); + } + } + + @Override + public void unregisterDisplayDevice(IDisplayDevice displayDevice) { + synchronized (getSyncRoot()) { + for (RemoteDisplay display: mDevices.values()) { + if (display.displayDevice == displayDevice) { + mDevices.remove(display.info.address); + if (mActiveDisplay == display) { + disconnectRemoteDisplay(); + } + return; + } + } + } + } + + @Override + public void scanRemoteDisplays() { + synchronized (getSyncRoot()) { + mScanning = true; + Intent scan = new Intent(SCAN); + PackageManager pm = getContext().getPackageManager(); + List services = pm.queryIntentServices(scan, 0); + if (services == null) + return; + for (ResolveInfo info : services) { + Intent intent = new Intent(); + ComponentName name = new ComponentName(info.serviceInfo.packageName, + info.serviceInfo.name); + intent.setComponent(name); + intent.setAction(SCAN); + getContext().startService(intent); + } + handleSendStatusChangeBroadcast(); + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + stopScan(); + } + }, 10000L); + } + } + + @Override + public void connectRemoteDisplay(String address) throws RemoteException { + synchronized (getSyncRoot()) { + RemoteDisplay display = mDevices.get(address); + if (display == null) { + Log.e(TAG, "Could not find display?"); + return; + } + if (display.remoteDisplayDevice != null) { + Log.e(TAG, "Display device is already connected?"); + return; + } + Surface surface; + try { + surface = display.displayDevice.createDisplaySurface(); + if (surface == null) { + Log.e(TAG, "Returned null Surface"); + return; + } + } catch (RemoteException e) { + Log.e(TAG, "Error creating surface", e); + return; + } + IBinder displayToken = SurfaceControl.createDisplay(display.info.name, false); + display.remoteDisplayDevice = new RemoteDisplayDevice(surface, displayToken, + display.info); + mActiveDisplay = display; + sendDisplayDeviceEventLocked(display.remoteDisplayDevice, + DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED); + handleSendStatusChangeBroadcast(); + + new Runnable() { + public void run() { + RemoteDisplay activeDisplay = mActiveDisplay; + if (activeDisplay == null) + return; + if (activeDisplay.displayDevice == null) + return; + if (activeDisplay.displayDevice.asBinder().isBinderAlive()) { + mHandler.postDelayed(this, 5000); + return; + } + synchronized (getSyncRoot()) { + stopActiveDisplayLocked(); + } + } + }.run(); + } + } + + @Override + public void disconnectRemoteDisplay() { + synchronized (getSyncRoot()) { + stopActiveDisplayLocked(); + handleSendStatusChangeBroadcast(); + } + } + + @Override + public void forgetRemoteDisplay(String address) { + synchronized (getSyncRoot()) { + } + } + + @Override + public void renameRemoteDisplay(String address, String alias) { + synchronized (getSyncRoot()) { + } + } + + @Override + public WifiDisplayStatus getRemoteDisplayStatus() { + synchronized (getSyncRoot()) { + ArrayList availableDisplays = new ArrayList(); + ArrayList list = new ArrayList(mDevices.values()); + for (RemoteDisplay display : list) { + if (!display.displayDevice.asBinder().isBinderAlive()) { + mDevices.remove(display.info.address); + if (mActiveDisplay == display) { + stopActiveDisplayLocked(); + } + continue; + } + WifiDisplay add = new WifiDisplay(display.info.address, display.info.name, + display.info.name, display.hidden); + availableDisplays.add(add); + } + + WifiDisplay active = null; + if (mActiveDisplay != null) + active = new WifiDisplay(mActiveDisplay.info.address, mActiveDisplay.info.name, + mActiveDisplay.info.name); + + WifiDisplayStatus status = new WifiDisplayStatus( + WifiDisplayStatus.FEATURE_STATE_ON, + mScanning ? WifiDisplayStatus.SCAN_STATE_SCANNING + : WifiDisplayStatus.SCAN_STATE_NOT_SCANNING, + WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED, active, + availableDisplays.toArray(new WifiDisplay[0]), WifiDisplay.EMPTY_ARRAY); + return status; + } + } + }; + + private void stopActiveDisplayLocked() { + if (mActiveDisplay != null && mActiveDisplay.remoteDisplayDevice != null) { + try { + mActiveDisplay.displayDevice.stop(); + } catch (Exception e) { + } + mActiveDisplay.remoteDisplayDevice.clearSurfaceLocked(); + sendDisplayDeviceEventLocked(mActiveDisplay.remoteDisplayDevice, + DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED); + mActiveDisplay.remoteDisplayDevice = null; + } + mActiveDisplay = null; + } + + public void stopScan() { + mScanning = false; + Intent scan = new Intent(SCAN); + PackageManager pm = getContext().getPackageManager(); + List services = pm.queryIntentServices(scan, 0); + if (services == null) { + return; + } + for (ResolveInfo info : services) { + Intent intent = new Intent(); + ComponentName name = new ComponentName(info.serviceInfo.packageName, + info.serviceInfo.name); + intent.setComponent(name); + intent.setAction(STOP_SCAN); + getContext().startService(intent); + } + handleSendStatusChangeBroadcast(); + } + + // Runs on the handler. + private void handleSendStatusChangeBroadcast() { + mHandler.post(new Runnable() { + @Override + public void run() { + final Intent intent = new Intent( + DisplayManager.ACTION_REMOTE_DISPLAY_STATUS_CHANGED); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + intent.putExtra(DisplayManager.EXTRA_REMOTE_DISPLAY_STATUS, + mStub.getRemoteDisplayStatus()); + + // Send protected broadcast about wifi display status to + // registered receivers. + getContext().sendBroadcastAsUser(intent, UserHandle.ALL); + } + }); + } + + private class RemoteDisplayDevice extends DisplayDevice { + private Surface surface; + private DisplayDeviceInfo mInfo; + + public RemoteDisplayDevice(Surface surface, IBinder displayToken, DisplayDeviceInfo info) { + super(RemoteDisplayAdapter.this, displayToken); + this.surface = surface; + this.mInfo = info; + } + + public void clearSurfaceLocked() { + surface = null; + sendTraversalRequestLocked(); + } + + @Override + public void performTraversalInTransactionLocked() { + setSurfaceInTransactionLocked(surface); + } + + @Override + public DisplayDeviceInfo getDisplayDeviceInfoLocked() { + synchronized (getSyncRoot()) { + return mInfo; + } + } + } + + public RemoteDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, Context context, + Handler handler, Listener listener, PersistentDataStore persistentDataStore) { + super(syncRoot, context, handler, listener, TAG); + this.mHandler = new Handler(handler.getLooper()); + } +} From bba7d609255d021448cd6cf22736415b24bf85ed Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Thu, 24 Oct 2013 19:51:30 -0700 Subject: [PATCH 096/204] Fix checkapi Change-Id: I231b2dbdb0ab2c59bf8f0ba96e9f0da1303b8c7e --- core/java/android/hardware/display/DisplayManager.java | 6 ++++++ core/java/android/hardware/display/IDisplayDevice.aidl | 3 +++ .../android/hardware/display/IRemoteDisplayAdapter.aidl | 3 +++ 3 files changed, 12 insertions(+) diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 1f315becea3a9..4af09d4719c40 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -66,9 +66,15 @@ public final class DisplayManager { public static final String EXTRA_WIFI_DISPLAY_STATUS = "android.hardware.display.extra.WIFI_DISPLAY_STATUS"; + /** + * @hide + */ public static final String ACTION_REMOTE_DISPLAY_STATUS_CHANGED = "android.hardware.display.action.REMOTE_DISPLAY_STATUS_CHANGED"; + /** + * @hide + */ public static final String EXTRA_REMOTE_DISPLAY_STATUS = "android.hardware.display.extra.REMOTE_DISPLAY_STATUS"; diff --git a/core/java/android/hardware/display/IDisplayDevice.aidl b/core/java/android/hardware/display/IDisplayDevice.aidl index a07165db8d49d..75e00da17285e 100644 --- a/core/java/android/hardware/display/IDisplayDevice.aidl +++ b/core/java/android/hardware/display/IDisplayDevice.aidl @@ -18,6 +18,9 @@ package android.hardware.display; import android.view.Surface; +/** + * @hide + */ interface IDisplayDevice { Surface createDisplaySurface(); oneway void stop(); diff --git a/core/java/android/hardware/display/IRemoteDisplayAdapter.aidl b/core/java/android/hardware/display/IRemoteDisplayAdapter.aidl index b945f654e6879..46892b68980e1 100644 --- a/core/java/android/hardware/display/IRemoteDisplayAdapter.aidl +++ b/core/java/android/hardware/display/IRemoteDisplayAdapter.aidl @@ -19,6 +19,9 @@ package android.hardware.display; import android.hardware.display.WifiDisplayStatus; import android.hardware.display.IDisplayDevice; +/** + * @hide + */ interface IRemoteDisplayAdapter { // No permissions required. oneway void scanRemoteDisplays(); From 12d072180855fdab7ad2529622437037b3aea8e4 Mon Sep 17 00:00:00 2001 From: Ethan Chen Date: Thu, 24 Oct 2013 22:27:09 -0700 Subject: [PATCH 097/204] NetworkController: Fix hiding signal strength icon when no SIM icon shown * This now handles the case where the no SIM icon is overlaid with the * signal strength icon when WiFi is disabled or not connected. Change-Id: Ie5bf3d9f5cb4752ff631c8fcf7b1a5628219b31b --- .../systemui/statusbar/policy/MSimNetworkController.java | 4 +++- .../android/systemui/statusbar/policy/NetworkController.java | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java index f7f2d77a46fd7..f950c71418044 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MSimNetworkController.java @@ -986,7 +986,9 @@ else if (!mMSimDataConnected[subscription] && !mWifiConnected && !mBluetoothTeth } else if (mPhone.isNetworkRoaming(subscription)) { mMSimDataTypeIconId[subscription] = R.drawable.stat_sys_data_connected_roam; } - } else if (mMSimState[subscription] == IccCardConstants.State.ABSENT) { + } + + if (!mAirplaneMode && mMSimState[subscription] == IccCardConstants.State.ABSENT) { mMSimPhoneSignalIconId[subscription] = mMSimDataSignalIconId[subscription] = mMSimDataTypeIconId[subscription] = 0; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 479dca6e0147f..1d51841e67dfd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -1271,7 +1271,9 @@ void refreshViews() { mDataTypeIconId = R.drawable.stat_sys_data_connected_roam; mQSDataTypeIconId = R.drawable.ic_qs_signal_r; } - } else if (mSimState == IccCardConstants.State.ABSENT) { + } + + if (!mAirplaneMode && mSimState == IccCardConstants.State.ABSENT) { // look again; your radios are now sim cards mPhoneSignalIconId = mDataSignalIconId = mDataTypeIconId = mQSDataTypeIconId = 0; mQSPhoneSignalIconId = 0; From 7eea6131e71862b2db7ac8fa3f508e276629a901 Mon Sep 17 00:00:00 2001 From: Phil Tunstall Date: Fri, 25 Oct 2013 00:30:34 +0100 Subject: [PATCH 098/204] Make lock screen menu button actions work regardless of rebinding Fixes 'Menu unlock' and (Lock screen->Button actions->)'Long press Menu button' when the menu button is assigned to an action other than its default. Change-Id: I4c2e2cf47fa2f0c171e3599cdc36bc744a708c3b --- .../android/internal/policy/impl/PhoneWindowManager.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index d4a4db9473544..791b4684bc566 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -2384,7 +2384,7 @@ public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int p // Hijack modified menu keys for debugging features final int chordBug = KeyEvent.META_SHIFT_ON; - if (virtualKey) { + if (virtualKey || keyguardOn) { // Let the app handle the key return 0; } @@ -2417,7 +2417,7 @@ public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int p return -1; } } else if (longPress) { - if (!keyguardOn && mLongPressOnMenuBehavior != KEY_ACTION_NOTHING) { + if (mLongPressOnMenuBehavior != KEY_ACTION_NOTHING) { if (mLongPressOnMenuBehavior != KEY_ACTION_APP_SWITCH) { cancelPreloadRecentApps(); } @@ -2435,7 +2435,7 @@ public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int p if (mPressOnMenuBehavior != KEY_ACTION_APP_SWITCH) { cancelPreloadRecentApps(); } - if (!canceled && !keyguardOn) { + if (!canceled) { performKeyAction(mPressOnMenuBehavior); } } From 35b195f16d1508dd6069bcd4aa88a17a9dd56f10 Mon Sep 17 00:00:00 2001 From: Marco Brohet Date: Fri, 25 Oct 2013 13:37:57 +0000 Subject: [PATCH 099/204] Revert "Frameworks/base: move custom string in cm_strings.xml file" CAF stays in strings.xml This reverts commit e03e106487c630458815cc9c5a523842b3159ba3. Change-Id: Idd6fbaf76a3a00b9790e876da8ce9b7555901cb6 --- core/res/res/values/cm_strings.xml | 3 --- core/res/res/values/strings.xml | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/res/res/values/cm_strings.xml b/core/res/res/values/cm_strings.xml index 536ea194c6c57..0c0ad9c202550 100644 --- a/core/res/res/values/cm_strings.xml +++ b/core/res/res/values/cm_strings.xml @@ -88,9 +88,6 @@ Discharging, %d%% - - No removable media present\u2026 - Dock SD card diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 39d9b1257ec9d..0104a36236da1 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3646,6 +3646,8 @@ Unmounting USB storage\u2026 Unmounting SD card\u2026 + + No removable media present\u2026 Erasing USB storage\u2026 From 52a6350f6d158df57114d09b16e797f3242532d2 Mon Sep 17 00:00:00 2001 From: Marco Brohet Date: Fri, 25 Oct 2013 16:21:45 +0200 Subject: [PATCH 100/204] core: NL translations Change-Id: I96149c3935825431fcf120b0d6cb1da839e01643 --- core/res/res/values-nl/cm_strings.xml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/core/res/res/values-nl/cm_strings.xml b/core/res/res/values-nl/cm_strings.xml index 53392bd4d9b9d..fe5bd662329fc 100644 --- a/core/res/res/values-nl/cm_strings.xml +++ b/core/res/res/values-nl/cm_strings.xml @@ -1,5 +1,6 @@ - + Mislukt. SIM/RUIM-vergrendeling inschakelen. + Pukcode ongeldig + PIN-bewerking mislukt + PUK-bewerking mislukt + Code correct + \nResterende pogingen: + Kaart ongeldig + Simkaart is ongeldig + SIM/RUIM bevat Perso-vergrendeling. + USSD-verzoek veranderd naar DIAL-verzoek. + USSD-verzoek veranderd naar SS-verzoek. + USSD-verzoek veranderd naar nieuw USSD-verzoek. + SS-verzoek veranderd naar DIAL-verzoek. + SS-verzoek veranderd naar USSD-verzoek. + SS-verzoek veranderd naar nieuw SS-verzoek. + ABON.:%d : %s. + %s, %s + Standaard Zakelijk Thuis From 9bf0b99619f246fe8e65530663d2d36e4182c5a4 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Fri, 25 Oct 2013 20:51:43 +0300 Subject: [PATCH 101/204] core: EL translations Signed-off-by: Michael Bestas Change-Id: I29841b15bd9a2c3346d0989e417eac89a2126e3a --- core/res/res/values-el/cm_strings.xml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/core/res/res/values-el/cm_strings.xml b/core/res/res/values-el/cm_strings.xml index aa75e151f3b86..f429d08e3b39b 100644 --- a/core/res/res/values-el/cm_strings.xml +++ b/core/res/res/values-el/cm_strings.xml @@ -1,5 +1,6 @@ - - "Reporniţi tablet PC" - "Reporniţi telefonul" - "Repornire" - "Repornire..." - "Recuperare" - "Telefonul dvs. va reporni." - "General" - "Serviciu" - "Acasă" - "Silenţios" - "Noapte" - "Telefon" - "Calendar" - "Gmail" - "Email" - "SMS" - "Desktop extins" - "Activat" - "Dezactivat" - "Repornire" - "Profil" - "Descărcare, %d%%" - "Rotire Ecran Deblocată" - "Rotire Ecran Blocată" - "Aplicaţie oprită" + Implicit + Serviciu + Acasă + Silențios + Noapte + Telefon + Calendar + SMS + Altele + Reporniți tableta + Reporniți telefonul + Captură de ecran + Suprafață de lucru extinsă + Pornit + Oprit + Repornire + Recuperare + Bootloader + Descărcare + Repornire\u2026 + Tableta va reporni. + Telefonul va reporni. + împiedică butonul pornire/oprire + Permite aplicației sa modifice butonul pornire/oprire + controlează receptorul FM + Permite aplicației să controleze receptorul FM. + controlează transmiţătorul FM + Permite aplicației să controleze transmiţătorul FM. + trimite mesaje SMS de batjocură + Permite aplicației sa trimită mesaje SMS de batjocură. Aceasta permite trimiterea de mesaje SMS către o aplicație de încredere. Aplicațiile rău intenționate pot trimite mesaje in continuu, blocând sistemul de notificare și deranjând utilizatorul. + Descărcare, %d%% + Stand card SD + Aplicație inchisă + Repornire + Profil + Rotirea ecranului deblocată + Rotirea ecranului blocată + %s nu este instalată + pornește sau oprește protejarea confidenţialitații + Permite aplicațiilor rularea in modul Protejarea Confidențialității. Când o aplicație ruleaza in modul Protejarea Confidențialității, nu va avea acces la datele personale cum ar fi contactele, jurnalul de apel sau mesajele. + Protejarea Confidențialității activată + %1$s nu va avea acces la datele personale + Profiluri + Niciunul + anulează notificările aplicației + Permite anularea notificărilor create de alte aplicații. + interceptarea mesajelor SMS trimise + Permite interceptarea mesajelor SMS trimise. Aplicațiile rău intenționate pot folosi asta pentru a impiedica trimiterea mesajelor SMS. + Impune SELinux + Comutare politică SELinux impusă sau permisivă. + Impune MMAC + Comutare politică MMAC impusă sau permisivă. From dac68b18f265d2e60dff974e6bacfb21b2f8fa86 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Wed, 30 Oct 2013 19:58:01 +0000 Subject: [PATCH 109/204] MiniThumbFile: Fix image/bitmap retrieval Change I66005dd69b0a5c8f4353bd7a8225d163a654fd2d changed the insertion and creation indexing mechanism, but the retrieval method was still using the old sparse one. Fixit Fixes android.provider.cts.MediaStore_Images_MediaTest#testInsertImageWithBitmap, android.provider.cts.MediaStore_Images_MediaTest#testInsertImageWithImagePath, android.provider.cts.MediaStore_Images_ThumbnailsTest#testQueryExternalMiniThumbnails, and android.provider.cts.MediaStore_Video_ThumbnailsTest#testGetThumbnail Change-Id: I41feea79fa304635f3908055fb95a8c85718a97f --- media/java/android/media/MiniThumbFile.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/media/java/android/media/MiniThumbFile.java b/media/java/android/media/MiniThumbFile.java index 98258570738c5..e9b4b4d923238 100644 --- a/media/java/android/media/MiniThumbFile.java +++ b/media/java/android/media/MiniThumbFile.java @@ -394,7 +394,11 @@ public synchronized void saveMiniThumbToFile(byte[] data, long id, long magic) RandomAccessFile r = miniThumbDataFile(); if (r == null) return null; - long pos = id * BYTES_PER_MINTHUMB; + long pos = getIndex(id, false); + if(pos < 0) return null; + + pos *= BYTES_PER_MINTHUMB; + FileLock lock = null; try { mBuffer.clear(); From f9a07cb03a53d92e65e75741eba1f8d33cecfa84 Mon Sep 17 00:00:00 2001 From: Ethan Chen Date: Wed, 30 Oct 2013 14:59:09 -0700 Subject: [PATCH 110/204] Move CM config options after AOSP config options Change-Id: I641a350fc9b6cc3af60ee818f90a826aba64f087 --- core/res/res/values/config.xml | 106 +++++++++++++++++---------------- 1 file changed, 54 insertions(+), 52 deletions(-) diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index eab7a5b739a73..7b75b596cb681 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -277,9 +277,6 @@ note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" --> - - true - false @@ -309,10 +306,6 @@ Default value is 2 minutes. --> 120000 - - false - false @@ -394,14 +387,6 @@ a car dock make the accelerometer more a physical input (like a lid). --> true - - false - - - false - false - - false - - - false - 2875 @@ -554,9 +533,6 @@ false - - false - true @@ -654,10 +630,6 @@ - 255 - 0 - false - @@ -752,9 +724,6 @@ com.android.location.fused - - com.qualcomm.services.location - true @@ -806,9 +775,6 @@ cell broadcasting sms, and MMS. --> true - - false - true @@ -920,14 +886,6 @@ false - - - - false @@ -1167,16 +1125,6 @@ 100 - - - 0 - 50 - 100 - 50 - - false @@ -1212,6 +1160,60 @@ com.android.inputmethod.latin + + + + true + + + false + + + false + + + false + + + false + + + false + + + false + + 255 + 0 + false + + + com.qualcomm.services.location + + + false + + + + + + + + 0 + 50 + 100 + 50 + + true From 087015c88577e824b1f90bea3afec4e9740b793b Mon Sep 17 00:00:00 2001 From: rheeze Date: Sun, 27 Oct 2013 14:42:42 +0100 Subject: [PATCH 111/204] core: IT translations Change-Id: Ie723b490cf890a6f81fa534d72ed6676e67f1644 --- core/res/res/values-it/cm_strings.xml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/core/res/res/values-it/cm_strings.xml b/core/res/res/values-it/cm_strings.xml index d3fb47f1378b6..4b5f8b42b0ab2 100644 --- a/core/res/res/values-it/cm_strings.xml +++ b/core/res/res/values-it/cm_strings.xml @@ -14,6 +14,25 @@ limitations under the License. --> + Conversazioni + Non ci sono dispositivi di memoria estraibili\u2026 + Non eseguito. Abilitare prima il blocco SIM/RUIM. + Codice PUK errato! + Errore nell\'operazione PIN! + Errore nell\'operazione PUK! + Codice valido! + \nTentativi rimanenti: + Tessera non valida. + La tessera SIM non è valida. + SIM/RUIM con blocco personalizzato + Richiesta USSD modificata in richiesta DIAL. + Richiesta USSD modificata in richiesta SS. + Richiesta USSD modificata in nuova richiesta USSD. + Richiesta SS modificata in richiesta DIAL. + Richiesta SS modificata in richiesta USSD. + Richiesta SS modificata in nuova richiesta SS. + SUS:%d : %s. + %s, %s Predefinito Lavoro Casa @@ -43,7 +62,6 @@ modifica azione tasto spegnimento Consente a un\'applicazione di cambiare il comportamento del tasto di spegnimento In uso, %d%% - Nessun supporto rimovibile presente\u2026 Applicazione terminata Riavvia Profilo From dee3db5b76f90d8ab99f390acc269ac1fd81a815 Mon Sep 17 00:00:00 2001 From: Darescu Ionut Date: Tue, 29 Oct 2013 12:17:31 +0200 Subject: [PATCH 112/204] SystemUI: Romanian translations Change-Id: Ia5ab2150fa01c78f8e2aa52c6f21c6615b7cd54b --- .../SystemUI/res/values-ro/cm_strings.xml | 72 +++++++++++++++---- 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/packages/SystemUI/res/values-ro/cm_strings.xml b/packages/SystemUI/res/values-ro/cm_strings.xml index c9abb211ed777..f027e4b075113 100644 --- a/packages/SystemUI/res/values-ro/cm_strings.xml +++ b/packages/SystemUI/res/values-ro/cm_strings.xml @@ -14,17 +14,63 @@ limitations under the License. --> - "GPS" - "Adormire" - "Sunet activat" - "Sunet dezactivat" - "Vibrare activată" - "Vibrare dezactivată" - "Activat" - "Dezactivat" - "Sunet" - "Ecran Blocare" - "Mod Reţea" - "Raport Erori" + HSPA+ + DCHSPAP + Sunet%s. + Vibrare%s. + Folosește capul lui Cid + Folosește capul lui Cid in locul bomboanelor gumate înăuntrul visului + Profil + Inactivitate ecran setată la: %1$d %2$s + GPS + GPS + Stinge ecran + Sunet + Sunet + Vibrare + Vibrare + Pornit + Oprit + Sunet + Blocare ecran + Mod rețea + Raport erori Sincronizare - + Sincronizare + Lanternă + Lanternă + NFC + NFC + Inactivitate ecran + Deconectat + USB Tether + USB Tether + Hotspot Wi-Fi + Hotspot Wi-Fi + Ore de liniște + Ore de liniște + LTE + LTE + Volum + Cameră + ADB în rețea + ADB în rețea + Extins + Normal + Nu se poate conecta la cameră + Atribuie o acțiune + Buttonul Acasă + Buttonul Recent + Buttonul Caută + Buttonul Înapoi + Button Gol + Butonul Meniu (auto ascunde) + Butonul Meniu (arată mereu) + Butonul Meniu + Încarcă (%d%%) + Încărcat + %d%% rămas + Fără serviciu + Mod avion pornit + Doar apeluri de urgență + \ No newline at end of file From dd3cf3564531245b85f70bfbb4af26fed43ee78d Mon Sep 17 00:00:00 2001 From: Vladislav Koldobskiy Date: Mon, 7 Oct 2013 00:46:55 +0400 Subject: [PATCH 113/204] Camera button support: useful features & bugfixes (1/2) Screw the remapping, let's make something more useful! Replaced the code to actually launch Camera app, not just fire the shutter. I won't remove it: it's cool to have an option to double-click Home for Camera. Added: * Camera wake (with button half-press) and unlock options * "Peek": releasing the half-pressed Camera button will turn the screen back off * Camera playback control Change-Id: Id49e09e20d81cd80d9800ab8ab0f200d44485a09 --- core/java/android/provider/Settings.java | 75 +++++++------- core/res/res/values/config.xml | 4 + core/res/res/values/symbols.xml | 1 + .../policy/impl/PhoneWindowManager.java | 97 ++++++++++++++++++- .../impl/keyguard/KeyguardHostView.java | 15 +++ .../impl/keyguard/KeyguardViewManager.java | 8 ++ 6 files changed, 162 insertions(+), 38 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 099593b38efd4..373cca72de028 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2941,6 +2941,24 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean */ public static final String VOLBTN_MUSIC_CONTROLS = "volbtn_music_controls"; + /** + * Whether to wake the screen with the camera key half-press. + * @hide + */ + public static final String CAMERA_WAKE_SCREEN = "camera_wake_screen"; + + /** + * Whether or not to send device back to sleep if Camera button is released ("Peek") + * @hide + */ + public static final String CAMERA_SLEEP_ON_RELEASE = "camera_sleep_on_release"; + + /** + * Whether or not camera button music controls should be enabled to play/pause media tracks + * @hide + */ + public static final String CAMERA_MUSIC_CONTROLS = "camera_music_controls"; + /** * Whether or not to launch default music player when headset is connected * @hide @@ -3137,6 +3155,12 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean */ public static final String HOME_UNLOCK_SCREEN = "home_unlock_screen"; + /** + * Whether to unlock the screen with the camera key. The value is boolean (1 or 0). + * @hide + */ + public static final String CAMERA_UNLOCK_SCREEN = "camera_unlock_screen"; + /** * Whether the lockscreen vibrate should be enabled. * @hide @@ -3208,41 +3232,26 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean */ public static final String LOCKSCREEN_MAXIMIZE_WIDGETS = "lockscreen_maximize_widgets"; - /** - * Action to perform when the assistant (search) key is long-pressed. (Default is 4) - * (See KEY_HOME_LONG_PRESS_ACTION for valid values) - * @hide - */ - public static final String KEY_ASSIST_LONG_PRESS_ACTION = "key_assist_long_press_action"; - - /** - * Action to perform when the app switch key is pressed. (Default is 2) - * (See KEY_HOME_LONG_PRESS_ACTION for valid values) - * @hide - */ - public static final String KEY_APP_SWITCH_ACTION = "key_app_switch_action"; - - /** - * Action to perform when the app switch key is long-pressed. (Default is 0) - * (See KEY_HOME_LONG_PRESS_ACTION for valid values) - * @hide - */ - public static final String KEY_APP_SWITCH_LONG_PRESS_ACTION = "key_app_switch_long_press_action"; - - /** - * Action to perform when the Camera key is pressed. (Default is 0) - * (See KEY_HOME_LONG_PRESS_ACTION for valid values) - * @hide - */ - public static final String KEY_CAMERA_ACTION = "key_camera_action"; + /** + * Action to perform when the assistant (search) key is long-pressed. (Default is 4) + * (See KEY_HOME_LONG_PRESS_ACTION for valid values) + * @hide + */ + public static final String KEY_ASSIST_LONG_PRESS_ACTION = "key_assist_long_press_action"; - /** - * Action to perform when the Camera key is long-pressed. (Default is 6) - * (See KEY_HOME_LONG_PRESS_ACTION for valid values) - * @hide - */ - public static final String KEY_CAMERA_LONG_PRESS_ACTION = "key_camera_long_press_action"; + /** + * Action to perform when the app switch key is pressed. (Default is 2) + * (See KEY_HOME_LONG_PRESS_ACTION for valid values) + * @hide + */ + public static final String KEY_APP_SWITCH_ACTION = "key_app_switch_action"; + /** + * Action to perform when the app switch key is long-pressed. (Default is 0) + * (See KEY_HOME_LONG_PRESS_ACTION for valid values) + * @hide + */ + public static final String KEY_APP_SWITCH_LONG_PRESS_ACTION = "key_app_switch_long_press_action"; /** * Control the display of the action overflow button within app UI. diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 7b75b596cb681..5dadc3244325a 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1249,6 +1249,10 @@ config to 7. --> 15 + + false + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 4cbff9d29a6aa..5d4d510eecf5c 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1918,6 +1918,7 @@ + diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 755fab36ea955..ecd94895116d8 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -324,6 +324,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mBackKillTimeout; int mPointerLocationMode = 0; // guarded by mLock int mDeviceHardwareKeys; + boolean mSingleStageCameraKey; boolean mHasMenuKeyEnabled; int mCurrentUser = 0; @@ -338,9 +339,17 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Behavior of volume wake boolean mVolumeWakeScreen; - // Behavior of volbtn music controls + // Behavior of camera wake + boolean mCameraWakeScreen; + boolean mCameraSleepOnRelease; + boolean mIsFocusPressed; + + // Behavior of volbtn/camera music controls + boolean mCameraMusicControls; boolean mVolBtnMusicControls; boolean mIsLongPress; + boolean mCameraKeyPressable = false; + private boolean mAnimatingWindows; private boolean mNeedUpdateSettings; @@ -599,9 +608,18 @@ void observe() { resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.VOLUME_WAKE_SCREEN), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.CAMERA_WAKE_SCREEN), false, this, + UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.CAMERA_SLEEP_ON_RELEASE), false, this, + UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.VOLBTN_MUSIC_CONTROLS), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.CAMERA_MUSIC_CONTROLS), false, this, + UserHandle.USER_ALL); resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.ACCELEROMETER_ROTATION), false, this, UserHandle.USER_ALL); @@ -999,7 +1017,7 @@ private void performKeyAction(int behavior) { triggerVirtualKeypress(KeyEvent.KEYCODE_SEARCH); break; case KEY_ACTION_LAUNCH_CAMERA: - triggerVirtualKeypress(KeyEvent.KEYCODE_CAMERA); + launchCameraAction(); break; default: break; @@ -1127,6 +1145,8 @@ public void init(Context context, IWindowManager windowManager, com.android.internal.R.integer.config_backKillTimeout); mDeviceHardwareKeys = mContext.getResources().getInteger( com.android.internal.R.integer.config_deviceHardwareKeys); + mSingleStageCameraKey = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_singleStageCameraKey); updateKeyAssignments(); @@ -1418,8 +1438,16 @@ public void updateSettings() { Settings.System.HOME_WAKE_SCREEN, 1, UserHandle.USER_CURRENT) == 1); mVolumeWakeScreen = (Settings.System.getIntForUser(resolver, Settings.System.VOLUME_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1); + mCameraWakeScreen = (Settings.System.getIntForUser(resolver, + Settings.System.CAMERA_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1); + mCameraSleepOnRelease = ((Settings.System.getIntForUser(resolver, + Settings.System.CAMERA_SLEEP_ON_RELEASE, 0, UserHandle.USER_CURRENT) == 1) + && mCameraWakeScreen); mVolBtnMusicControls = (Settings.System.getIntForUser(resolver, Settings.System.VOLBTN_MUSIC_CONTROLS, 1, UserHandle.USER_CURRENT) == 1); + mCameraMusicControls = ((Settings.System.getIntForUser(resolver, + Settings.System.CAMERA_MUSIC_CONTROLS, 1, UserHandle.USER_CURRENT) == 1) + && !mCameraWakeScreen); updateKeyAssignments(); @@ -2792,6 +2820,13 @@ private void launchAssistAction() { } } + private void launchCameraAction() { + sendCloseSystemWindows(); + Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null); + mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF, + null, null, null, 0, null, null); + } + private SearchManager getSearchManager() { if (mSearchManager == null) { mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); @@ -4256,6 +4291,52 @@ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean i } } break; + case KeyEvent.KEYCODE_FOCUS: + if (down && !isScreenOn && mCameraWakeScreen) { + if (keyguardActive) { + mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode); + } else { + result |= ACTION_WAKE_UP; + } + if (mCameraSleepOnRelease) { + mIsFocusPressed = true; + } + } else if (!down && isScreenOn && mIsFocusPressed) { + result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP; + mIsFocusPressed = false; + } + break; + case KeyEvent.KEYCODE_CAMERA: + if (down && mIsFocusPressed) { + mIsFocusPressed = false; + } + if (down && !isScreenOn && mCameraWakeScreen && mSingleStageCameraKey) { + if (keyguardActive) { + mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode); + } else { + result |= ACTION_WAKE_UP; + } + } + if (mCameraMusicControls) { + // if the camera key is not pressable, see if music is active + if (!mCameraKeyPressable) { + mCameraKeyPressable = isMusicActive(); + } + + if (mCameraKeyPressable) { + if (down) { + Message msg = mHandler.obtainMessage(MSG_DISPATCH_VOLKEY_WITH_WAKE_LOCK, + new KeyEvent(event.getDownTime(), event.getEventTime(), + event.getAction(), KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, 0)); + msg.setAsynchronous(true); + mHandler.sendMessageDelayed(msg, ViewConfiguration.getLongPressTimeout()); + break; + } else { + mHandler.removeMessages(MSG_DISPATCH_VOLKEY_WITH_WAKE_LOCK); + } + } + } + break; case KeyEvent.KEYCODE_VOLUME_DOWN: case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_MUTE: { @@ -4491,7 +4572,7 @@ private boolean isWakeKeyWhenScreenOff(int keyCode) { case KeyEvent.KEYCODE_VOLUME_MUTE: return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED; - // ignore media and camera keys + // ignore media keys case KeyEvent.KEYCODE_MUTE: case KeyEvent.KEYCODE_HEADSETHOOK: case KeyEvent.KEYCODE_MEDIA_PLAY: @@ -4503,10 +4584,11 @@ private boolean isWakeKeyWhenScreenOff(int keyCode) { case KeyEvent.KEYCODE_MEDIA_REWIND: case KeyEvent.KEYCODE_MEDIA_RECORD: case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: - case KeyEvent.KEYCODE_CAMERA: return false; - // home wake can be configurable so default to no here + // home & camera wake can be configurable so default to no here + case KeyEvent.KEYCODE_FOCUS: + case KeyEvent.KEYCODE_CAMERA: case KeyEvent.KEYCODE_HOME: return false; } @@ -4692,6 +4774,11 @@ public void screenTurningOn(final ScreenOnListener screenOnListener) { } synchronized (mLock) { + // since the screen turned on, assume we don't enable play-pause again + // unless they turn it off and music is still playing. this is done to + // prevent the camera button from starting playback if playback wasn't + // originally running + mCameraKeyPressable = false; mScreenOnEarly = true; updateOrientationListenerLp(); updateLockScreenTimeout(); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java index f2f0a0f4051d0..ac69589a45db6 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java @@ -1742,6 +1742,11 @@ private boolean shouldEnableHomeKey() { return homeOverride; } + private boolean shouldEnableCameraKey() { + final boolean cameraOverride = Settings.System.getInt(getContext().getContentResolver(), Settings.System.CAMERA_UNLOCK_SCREEN, 0) == 1; + return cameraOverride; + } + public void goToUserSwitcher() { mAppWidgetContainer.setCurrentPage(getWidgetPosition(R.id.keyguard_multi_user_selector)); } @@ -1760,6 +1765,16 @@ public boolean handleMenuKey() { return false; } + + public boolean handleCameraKey() { + // The following enables the CAMERA key to work for testing automation + if (shouldEnableCameraKey()) { + showNextSecurityScreenOrFinish(false); + return true; + } + return false; + } + public boolean handleHomeKey() { // The following enables the HOME key to work for testing automation if (shouldEnableHomeKey()) { diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java index fe9288aefa184..ce7407c9f5c9a 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java @@ -181,6 +181,14 @@ public boolean dispatchKeyEvent(KeyEvent event) { public boolean handleKeyDown(int keyCode, KeyEvent event) { if (event.getRepeatCount() == 0) { mUnlockKeyDown = true; + // We check for Camera key press in handleKeyDown, because + // it gives us "instant" unlock, when user depresses + // the button. + if (keyCode == KeyEvent.KEYCODE_CAMERA) { + if (mKeyguardView.handleCameraKey()) { + return true; + } + } } if (event.isLongPress()) { String action = null; From 62cc2758b5b0cd9dcc1d8faf5836ce55e51cc28c Mon Sep 17 00:00:00 2001 From: Jorge Ruesga Date: Mon, 14 Oct 2013 02:24:55 +0200 Subject: [PATCH 114/204] Frameworks: QS performance profiles tile Patchset 2: Fix not null comparation Patchset 3: xxhdpi drawables Patchset 4: Fix xxhdpi drawables (thx blunden) Rebased Patchset 5: Add suggestions Sync on boot the system property with the setting Patchset 6: Rebased Change-Id: Ib32d3734b63f88a3473e0ab10d8edf30dae9ceb6 Signed-off-by: Jorge Ruesga --- core/java/android/provider/Settings.java | 7 + .../android/internal/util/cm/QSConstants.java | 1 + .../com/android/internal/util/cm/QSUtils.java | 8 ++ core/res/res/values-cs/cm_strings.xml | 4 + core/res/res/values-de/cm_strings.xml | 3 + core/res/res/values-el/cm_strings.xml | 3 + core/res/res/values-es/cm_strings.xml | 3 + core/res/res/values-hu/cm_strings.xml | 3 + core/res/res/values-it/cm_strings.xml | 3 + core/res/res/values-pt/cm_strings.xml | 5 +- core/res/res/values-ru/cm_strings.xml | 4 + core/res/res/values-sk/cm_strings.xml | 3 + core/res/res/values-zh-rTW/cm_strings.xml | 3 + core/res/res/values/cm_arrays.xml | 13 ++ core/res/res/values/cm_strings.xml | 5 + core/res/res/values/config.xml | 11 ++ core/res/res/values/symbols.xml | 10 ++ .../res/drawable-hdpi/ic_qs_perf_profile.png | Bin 0 -> 601 bytes .../drawable-hdpi/ic_qs_perf_profile_bal.png | Bin 0 -> 1047 bytes .../drawable-hdpi/ic_qs_perf_profile_perf.png | Bin 0 -> 929 bytes .../ic_qs_perf_profile_pwrsv.png | Bin 0 -> 1372 bytes .../res/drawable-mdpi/ic_qs_perf_profile.png | Bin 0 -> 572 bytes .../drawable-mdpi/ic_qs_perf_profile_bal.png | Bin 0 -> 826 bytes .../drawable-mdpi/ic_qs_perf_profile_perf.png | Bin 0 -> 743 bytes .../ic_qs_perf_profile_pwrsv.png | Bin 0 -> 997 bytes .../res/drawable-xhdpi/ic_qs_perf_profile.png | Bin 0 -> 616 bytes .../drawable-xhdpi/ic_qs_perf_profile_bal.png | Bin 0 -> 1080 bytes .../ic_qs_perf_profile_perf.png | Bin 0 -> 915 bytes .../ic_qs_perf_profile_pwrsv.png | Bin 0 -> 1741 bytes .../drawable-xxhdpi/ic_qs_perf_profile.png | Bin 0 -> 729 bytes .../ic_qs_perf_profile_bal.png | Bin 0 -> 1951 bytes .../ic_qs_perf_profile_perf.png | Bin 0 -> 1163 bytes .../ic_qs_perf_profile_pwrsv.png | Bin 0 -> 2410 bytes packages/SystemUI/res/values/cm_arrays.xml | 26 ++++ .../quicksettings/PerformanceProfileTile.java | 124 ++++++++++++++++++ .../phone/QuickSettingsController.java | 8 ++ .../java/com/android/server/SystemServer.java | 37 ++++++ 37 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 packages/SystemUI/res/drawable-hdpi/ic_qs_perf_profile.png create mode 100644 packages/SystemUI/res/drawable-hdpi/ic_qs_perf_profile_bal.png create mode 100644 packages/SystemUI/res/drawable-hdpi/ic_qs_perf_profile_perf.png create mode 100644 packages/SystemUI/res/drawable-hdpi/ic_qs_perf_profile_pwrsv.png create mode 100644 packages/SystemUI/res/drawable-mdpi/ic_qs_perf_profile.png create mode 100644 packages/SystemUI/res/drawable-mdpi/ic_qs_perf_profile_bal.png create mode 100644 packages/SystemUI/res/drawable-mdpi/ic_qs_perf_profile_perf.png create mode 100644 packages/SystemUI/res/drawable-mdpi/ic_qs_perf_profile_pwrsv.png create mode 100644 packages/SystemUI/res/drawable-xhdpi/ic_qs_perf_profile.png create mode 100644 packages/SystemUI/res/drawable-xhdpi/ic_qs_perf_profile_bal.png create mode 100644 packages/SystemUI/res/drawable-xhdpi/ic_qs_perf_profile_perf.png create mode 100644 packages/SystemUI/res/drawable-xhdpi/ic_qs_perf_profile_pwrsv.png create mode 100644 packages/SystemUI/res/drawable-xxhdpi/ic_qs_perf_profile.png create mode 100644 packages/SystemUI/res/drawable-xxhdpi/ic_qs_perf_profile_bal.png create mode 100644 packages/SystemUI/res/drawable-xxhdpi/ic_qs_perf_profile_perf.png create mode 100644 packages/SystemUI/res/drawable-xxhdpi/ic_qs_perf_profile_pwrsv.png create mode 100644 packages/SystemUI/res/values/cm_arrays.xml create mode 100644 packages/SystemUI/src/com/android/systemui/quicksettings/PerformanceProfileTile.java diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 099593b38efd4..3550eeb70c1b6 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3295,6 +3295,13 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean */ public static final String VOLUME_KEYS_CONTROL_RING_STREAM = "volume_keys_control_ring_stream"; + /** + * Performance profile + * @see config_perf_profile_prop in frameworks/base/core/res/res/values/config.xml + * @hide + */ + public static final String PERFORMANCE_PROFILE = "performance_profile"; + /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. diff --git a/core/java/com/android/internal/util/cm/QSConstants.java b/core/java/com/android/internal/util/cm/QSConstants.java index 77c91e4ac50d2..27cdaedc361bb 100644 --- a/core/java/com/android/internal/util/cm/QSConstants.java +++ b/core/java/com/android/internal/util/cm/QSConstants.java @@ -24,6 +24,7 @@ public class QSConstants { public static final String TILE_LTE = "toggleLte"; public static final String TILE_WIMAX = "toggleWimax"; public static final String TILE_PROFILE = "toggleProfile"; + public static final String TILE_PERFORMANCE_PROFILE = "togglePerformanceProfile"; public static final String TILE_NFC = "toggleNfc"; public static final String TILE_USBTETHER = "toggleUsbTether"; public static final String TILE_QUIETHOURS = "toggleQuietHours"; diff --git a/core/java/com/android/internal/util/cm/QSUtils.java b/core/java/com/android/internal/util/cm/QSUtils.java index 2ea60cbd34b09..f205a8a85c9f9 100644 --- a/core/java/com/android/internal/util/cm/QSUtils.java +++ b/core/java/com/android/internal/util/cm/QSUtils.java @@ -14,6 +14,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.telephony.TelephonyManager; +import android.text.TextUtils; import com.android.internal.telephony.PhoneConstants; @@ -46,6 +47,13 @@ public static boolean systemProfilesEnabled(ContentResolver resolver) { return (Settings.System.getInt(resolver, Settings.System.SYSTEM_PROFILES_ENABLED, 1) == 1); } + public static boolean deviceSupportsPerformanceProfiles(Context ctx) { + Resources res = ctx.getResources(); + String perfProfileProp = res.getString( + com.android.internal.R.string.config_perf_profile_prop); + return !TextUtils.isEmpty(perfProfileProp); + } + public static boolean expandedDesktopEnabled(ContentResolver resolver) { return (Settings.System.getIntForUser(resolver, Settings.System.EXPANDED_DESKTOP_STYLE, 0, UserHandle.USER_CURRENT_OR_SELF) != 0); diff --git a/core/res/res/values-cs/cm_strings.xml b/core/res/res/values-cs/cm_strings.xml index 6db3ac6b1b1f7..13437f2ff54ee 100644 --- a/core/res/res/values-cs/cm_strings.xml +++ b/core/res/res/values-cs/cm_strings.xml @@ -89,4 +89,8 @@ Přepnutí politiky SELinux na vynucující (enforcing) nebo tolerantní (permissive). Vynucení MMAC Přepnutí politiky MMAC na vynucující (enforcing) nebo tolerantní (permissive). + + Úsporný + Vyvážený + Výkonný diff --git a/core/res/res/values-de/cm_strings.xml b/core/res/res/values-de/cm_strings.xml index 1c227fdd04f0d..226ff74b26c86 100644 --- a/core/res/res/values-de/cm_strings.xml +++ b/core/res/res/values-de/cm_strings.xml @@ -71,4 +71,7 @@ Ermöglicht der App, die Anwendung der SELinux-Richtlinie zwischen strikt und moderat zu wechseln. MMAC-Richtlinie wechseln Ermöglicht der App, die Anwendung der MMAC-Richtlinie zwischen strikt und moderat zu wechseln. + Energie sparen + Ausgeglichen + Mehr Leistung diff --git a/core/res/res/values-el/cm_strings.xml b/core/res/res/values-el/cm_strings.xml index f429d08e3b39b..59e7424e1d617 100644 --- a/core/res/res/values-el/cm_strings.xml +++ b/core/res/res/values-el/cm_strings.xml @@ -144,4 +144,7 @@ Η αίτηση SS τροποποιήθηκε σε νέα αίτηση SS. ΣΥΝΔΡ.: %d: %s. %s, %s + Εξοικονόμηση ενέργειας + Ισορροπημένο + Επιδόσεις diff --git a/core/res/res/values-es/cm_strings.xml b/core/res/res/values-es/cm_strings.xml index f77e607a9747f..fde5b87451ada 100644 --- a/core/res/res/values-es/cm_strings.xml +++ b/core/res/res/values-es/cm_strings.xml @@ -90,4 +90,7 @@ Alternar entre el modo permisivo o restrictivo de SELinux. Forzar MMAC Alternar entre el modo permisivo o restrictivo de MMAC. + Ahorro de energía + Equilibrado + Alto rendimiento diff --git a/core/res/res/values-hu/cm_strings.xml b/core/res/res/values-hu/cm_strings.xml index 2a2306a865cee..7b2f5c9d6d3c8 100644 --- a/core/res/res/values-hu/cm_strings.xml +++ b/core/res/res/values-hu/cm_strings.xml @@ -88,4 +88,7 @@ SS kérés módosítva új SS kérésre. SUB:%d : %s. %s, %s + Energiatakarékos + Kiegyensúlyozott + Teljesítménycentrikus diff --git a/core/res/res/values-it/cm_strings.xml b/core/res/res/values-it/cm_strings.xml index 4b5f8b42b0ab2..7fafe526898eb 100644 --- a/core/res/res/values-it/cm_strings.xml +++ b/core/res/res/values-it/cm_strings.xml @@ -89,4 +89,7 @@ Alterna tra regole restrittive o permissive di SELinux. Forza MMAC Alterna tra regole restrittive o permissive di MMAC. + Risparmio energetico + Bilanciato + Prestazioni diff --git a/core/res/res/values-pt/cm_strings.xml b/core/res/res/values-pt/cm_strings.xml index 3eee0d1e03975..82601f4e2ec94 100644 --- a/core/res/res/values-pt/cm_strings.xml +++ b/core/res/res/values-pt/cm_strings.xml @@ -125,4 +125,7 @@ Permite ao aplicativo simular envio de mensagens SMS. Isto permite um aplicativo enviar SMS para aplicações confiáveis. Aplicativos maliciosos pode enviar mensagens continuamente, bloqueando o sistema de notificação do dispositivo e perturbar o usuário. Nenhuma mídia removível presente\u2026 - \ No newline at end of file + Economia + Balanceado + Performance + diff --git a/core/res/res/values-ru/cm_strings.xml b/core/res/res/values-ru/cm_strings.xml index 8fd3ad1a9cd05..c1d8930b1e409 100644 --- a/core/res/res/values-ru/cm_strings.xml +++ b/core/res/res/values-ru/cm_strings.xml @@ -73,4 +73,8 @@ Переключать принудительный и разрешающий режимы политики SELinux. Переключение режимов MMAC Переключать принудительный и разрешающий режимы политики MMAC. + + Экономия энергии + Сбалансированный + Высокая производительность diff --git a/core/res/res/values-sk/cm_strings.xml b/core/res/res/values-sk/cm_strings.xml index a1eb4ef6be7c4..648afc2ff9b34 100644 --- a/core/res/res/values-sk/cm_strings.xml +++ b/core/res/res/values-sk/cm_strings.xml @@ -72,4 +72,7 @@ posielať falošné SMS správy Povolí aplikácii odosielať falošné SMS správy. Toto povolenie umožňuje aplikácii posielať SMS do dôveryhodných aplikácií. Škodlivé aplikácie môžu posielať správy nepretržite, blokovať oznamovací systém zariadenia a vyrušovať užívateľa. Nie je dostupné žiadne vymeniteľné médium\u2026 + Úsporný + Vyvážený + Výkonný diff --git a/core/res/res/values-zh-rTW/cm_strings.xml b/core/res/res/values-zh-rTW/cm_strings.xml index 85e7d166af6a4..bfd497f278b85 100644 --- a/core/res/res/values-zh-rTW/cm_strings.xml +++ b/core/res/res/values-zh-rTW/cm_strings.xml @@ -124,4 +124,7 @@ 切換 SELinux 政策執行模式或許可模式。 執行 MMAC 切換 MMAC 政策執行模式或許可模式。 + 省電 + 平衡 + 效能 diff --git a/core/res/res/values/cm_arrays.xml b/core/res/res/values/cm_arrays.xml index ad8c044aa207f..6fac86768ec63 100644 --- a/core/res/res/values/cm_arrays.xml +++ b/core/res/res/values/cm_arrays.xml @@ -39,4 +39,17 @@ com.google.android.gsf|com.google.android.talk + + + @string/perf_profile_pwrsv + @string/perf_profile_bal + @string/perf_profile_perf + + + + 0 + 1 + 2 + + diff --git a/core/res/res/values/cm_strings.xml b/core/res/res/values/cm_strings.xml index 0c0ad9c202550..d04d93c0feb69 100644 --- a/core/res/res/values/cm_strings.xml +++ b/core/res/res/values/cm_strings.xml @@ -193,4 +193,9 @@ Toggle MMAC policy enforcing or permissive mode. + + Power save + Balanced + Performance + diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 7b75b596cb681..94f8e8b2c9e68 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1318,4 +1318,15 @@ The default value is false which represents AOSP behavior. --> false + + + + + + + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 4cbff9d29a6aa..92aeb459df488 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2089,4 +2089,14 @@ + + + + + + + + + + diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_perf_profile.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_perf_profile.png new file mode 100644 index 0000000000000000000000000000000000000000..9d7ba56b9805bea746a6d1b347ed3cdfe2208cc7 GIT binary patch literal 601 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?3oVGw3ym^DX&fq~I1 z)7d#7AS1sdzc?emK*7`5S)rgPKP@vSm4Tt+*4n;}UWWrj9L{$ydK93|Qdm$iSwmyn ztAt}qbX^73Tva@IZOKBfOrf~At931lquIsF_a8VJSP<}s>Ayqas|Ny#&CMM1UfwzU zwCLc98>Pz=rz8qwU(K_+^tHzF_Yt08h6|jVujFmzV|b*}_v7GmZKem6m)BYI{ySDP zLyOm^;cecORs}7G|4z%Ljz}0Z*R68A!??^U^SXl#!_v5S`VN{W{_<*QUjOV^!;p6V zYmLD(2ICX8tOlheD;cvqt%B0`2J5b#mg>2CHp@gCxl}8ulp=dR;i+n?7BAMD@Spua z(!LvcRz+*GBCB8jF<$rl^qqVC0u2#WI#G@mAy+tluB&A2{a!_eGR{5-?a5l0AZa85pWm85kOx85n;42huMX7=kz$7)2u( z7_6oaT z&)(|tzGBl2gWZM84- zp7Q4``B83Ue0DG6{p}rWpZ=dPXkg??U|^Owz`%yieBitiTC!#n)aHU21Y*V g2f#$~|35PW|EaCaDi=5Q03FKU>FVdQ&MBb@04LM*od5s; literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_perf_profile_bal.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_perf_profile_bal.png new file mode 100644 index 0000000000000000000000000000000000000000..7a847697490e05f4a9741e14985a2f8eca1e1d1f GIT binary patch literal 1047 zcmV+y1nB#TP)KLZ*U+R`sCEkzKl)gj5&q@hY_5?)@_euSf22N!q0z{yc?Q2YY_Kym8e z5Fvwu2%hQO!{u_psMvL#(bD64NQRTZj^-}DnS22ry9f-;mW=gZvQj}U-ZdMsK&I8^7~DvX`q=icvy%+(Wxn6{ z-V8BWma)zlvE~>YST!R5k0eP>-IS(j1~8pYO<6yVV^lQ*5D^3X(@&D5)_lG#aU2g6 z>J*G0MqLWcmvYr`snk0PMMZ+`5?q_&I5z!W0he!G)Ik3e*;&`XH9KeCbp<%-q6Q8` zS?sP!|=Ybn_9}Y)xdED@qPyG0q-hmz#V&LSF*VVTn}?rqiW=N3!Dq_x&S+Q z4)||9NTG%yH4k5b>HnZnEeGltEh5Hd)>(+J9!+in`@o5aL_WQ2xnZhmpm8$tCc0ST z(S7^7p{j3k#(%cT#5E(5+deMP*epPigPc<2J8-!wg+_VjLi4KvS9gF*z^{UPHs|yZ zk<7Mt?N|of^2YFuFSDubeqgUC`B=OFZs#P!r*0T6qjYFL&`QKLLUq+z=QVJ@RU%u! zp7=K~E=y#px>aQSs`tbjz>%ts1Hs}U@M+omfhPC{JOVxd7l6mMzx4e;Q(OgJ4(CF{ zxloVKg;u`;g9et2QJLqi_f`6CoEDK&{krpo-hTgAU>#tFZzTo?&bR}A2LR{UX{U#X R5KaI9002ovPDHLkV1hYD&olr4 literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_perf_profile_perf.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_perf_profile_perf.png new file mode 100644 index 0000000000000000000000000000000000000000..12b095f9bd1f0de97d61f33a0e8fcfdcc712e6b2 GIT binary patch literal 929 zcmV;S177@zP)KLZ*U+R`sCEkzKl)gj5&q@hY_5?)@_euSf22N!q0z{yc?Q2YY_Kym8e z5Fvwu2%hQO!{u_psMvL#(bD64NQRTZj^-}DnS22ry9f-;mW=gZvQj}U-ZdMsK&I8^7~DvX`q=il8YR8&mps>tGrDP z40Firy2^o1;44FB5!f=x0h1nh%ptSxavpffA#><*9(c)^Uj|lP&I2DA^V?SPfLts^ zQKYlaC}aMhr~zsLH?I!gU z;?%Y8g$iIaA#}P$7n5~Tb3z$C@gOC13YQVKd*b^Ep>tBDo>=Y5y0a>2s~<@4Dn0L% zQGu4pfj8hsDxc4dWJ!x0xRahcHm+PubKqGD9b@gI&3mCsETg#_oi{3fH(KwXn0(*& zWb5;c<;pP#g0Zpgdect7{vN0Tyym|WjRF7MfZqWCNbuDA@*_VR00000NkvXXu0mjf DY|@vr literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_perf_profile_pwrsv.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_perf_profile_pwrsv.png new file mode 100644 index 0000000000000000000000000000000000000000..12033e53869aa496c1750bd3a58854602d23c0e5 GIT binary patch literal 1372 zcmV-i1*7_jP)KLZ*U+R`sCEkzKl)gj5&q@hY_5?)@_euSf22N!q0z{yc?Q2YY_Kym8e z5Fvwu2%hQO!{u_psMvL#(bD64NQRTZj^-}DnS22ry9f-;mW=gZvQj}U-ZdMsK&I8^7~DvX`q=i&L_t(|+U%NNh*eb-#(zhy5}BdK6qL}zMGAwCL=W|#DH1x- zAbj=^1oL7Mp*DdpMlaz*L1a*Z5kb9#D9A$7m(s@mAdwJp%Vd(S6{uyD38RL}bbDwY z*ly1`_ntdv=G@70M4x9znNjj1! zB(==!b6{DobKqy-aUZ-VqrJ|7AAseOe$RM*6!- zum_k640^gNz>uWl0r<7Rcffg1{S`3O4F_r^?DAD$*m?6LaJ$pLEa}St{FA^6;6PyG z$0|ASx}?7yz#+Grhb6rlfS(II3%nv}BCv6)+k2pvmv1+l&352_1K#xF`KX!g0LD|k z`vTCCbTH-Fc-|yo0++jhr1>^WDHhX0{5r4cMDwYkpS2RoDXs zIB+cN2LMl)*+NO@fKPxWz-z!I;82dOd#m8U>0o>U7yy>LiLL^F0S^F2B%RK&^+;(R zD8Pa7;Ju4xRs$aN!sUef{b|nb-U+B%4s_HP%8;8h*e*{Iq#@*vuBEgwV}iLboVw_s#4v;Ny%iqzIgqw8@RnyOZOBnJohD0KRs>=K;RSmpSgT!%Va?2^+szYZpJoOw0z)ln?aWw-8Yp*ciDZRt-wB) z`z$L9E2Z_;&!`5t5_Rgnr)u0000Ayqas|Ny#&CMM1UfwzU zwCLc98>Pz=rz8qwU(K_+^tHzF_Yt08h6|jVujFmzV|b*}_v7GmZKem6m)BYI{ySDP zLyOm^;cecORs}7G|4z%Ljz}0Z*R68A!??^U^SXl#!_v5S`VN{W{_<*QUjOV^!;p6V zYmLD(2ICX8tOlheD;cvqt%B0`2J5b#mg>2CHp@gCxl}8ulp=dR;i+n?7BAMD@Spua z(!LvcRz+*GBCB8jF<$rl^qqVC0u2#WI#G@mAy+tluB&A2{a!_eGR{5-5z5J%W507^+km7#f-x7=Hc-(k~bof;bo$MI#s( ztfn(Ci05CAlAi!n+u-Tq7*cWT&Gds@2MjozAKwuFwea7f-4+r@=eC7L*of-;epU)8 zEHAm%_{?havYCtx%o8$d?N-0?VNW^RFmr0FQ|QxBhZ}X#Vc#AIOiD{QZt)}dgqA~@ zr9l}_X9GtE3`Gf?`6(K%r*`vbvH0Zsy35}(=>aYO|DTz`J>T6ud(*@PKrVx)tDnm{ Hr-UW|U<2wS literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_perf_profile_bal.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_perf_profile_bal.png new file mode 100644 index 0000000000000000000000000000000000000000..f41ffe8cdc69d1fe23a9e83629c2540e7c96b630 GIT binary patch literal 826 zcmV-A1I7G_P)KLZ*U+R`sCEkzKl)gj5&q@hY_5?)@_euSf22N!q0z{yc?Q2YY_Kym8e z5Fvwu2%hQO!{u_psMvL#(bD64NQRTZj^-}DnS22ry9f-;mW=gZvQj}U-ZdMsK&I8^7~DvX`q=i-=}NvN|msJS)s zjFJEnz6pi23*z$Bvs}VX6AwbJnbXODm$}R3ftk5c522Ct0(?n&OPOC|L;(exrq{RpcR6|@DyWcqz`bW_ zUDB4B4Knjl5>cq#WuzM9%>NYa(VVurNcsfU(z(G)^WlG&V%36BYx&&p4m<)oK&Os! z+yQJ><+zet@nYVH=I2&i<-?>Xh0ou^WZ@pCwFCGc0AGoj-P|mY#{d8T07*qoM6N<$ Ef>t+V>Hq)$ literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_perf_profile_perf.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_perf_profile_perf.png new file mode 100644 index 0000000000000000000000000000000000000000..7786939a477377fd6196c81b206b2273ff2eea08 GIT binary patch literal 743 zcmV?P)KLZ*U+R`sCEkzKl)gj5&q@hY_5?)@_euSf22N!q0z{yc?Q2YY_Kym8e z5Fvwu2%hQO!{u_psMvL#(bD64NQRTZj^-}DnS22ry9f-;mW=gZvQj}U-ZdMsK&I8^7~DvX`q=iBTffEgB=!RH1jajAz0G@J+i}pWQU+TfRSDyKrj~& z0B;x=80>J!)iW?Kgp->MiS_w89O4{ASWcBFIE+Kwh@2=OryO{WLp+tzl91Racz{Jr zfPsO*oL;%$85S{Ta&rNxQLqb#_*w=A1}!L_P0J{_L_l7JKw6+U3O?eI<6vN5=%sZO zG&3+TT!Ug2G`T1S1_o7nBKLZ*U+R`sCEkzKl)gj5&q@hY_5?)@_euSf22N!q0z{yc?Q2YY_Kym8e z5Fvwu2%hQO!{u_psMvL#(bD64NQRTZj^-}DnS22ry9f-;mW=gZvQj}U-ZdMsK&I8^7~DvX`q=iBHo80Ab29_5pWAw0&ctVHsBnv4t)2$pYw*`8!+bmXTTj`uaAd-0bo|rTEvZ9 zA$TEa!OXTvS^=H{M}6%yu;}bB%X;1rJodKF%!Vb+1G8o}0vt}AzG{+d1cLY8{sNAf z*$zoFzy+YgVTol|-Vl6^+Ad%)`hQ;1a%%rzmU?6@We;F9I)9*|Y~ZQv-rb zxnN%e!3xmn;a39QMamOk9N3dL1ZSh9Q*zI3_qdPUKMo9MtqE&I!ErM?DJl3R6oB0h z!CN!yHnRu7`3>}Cj)G2L%*+k~Z-A|Czzopu?WsBolFYfF7ntxUcn%x@MuBPINFG&j zJ*oH*a1VG02-sia(y1#7+SBz~9fl0}m$@cv&8oP_he;*Ht@|+f?;fX3H{kC8)OgIm TMvfZT00000NkvXXu0mjfw>YyY literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_perf_profile.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_perf_profile.png new file mode 100644 index 0000000000000000000000000000000000000000..e352ce4a5a3daed58101cedcf683d132df745c0c GIT binary patch literal 616 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9GG!XV7ZFl&wk0|TR3 zrn7TEKt_H^esM;Afr6*AvqC{pep+TuDg#5st+jm{y$%P6IGpcZ^e8}^rLdr4vWCXC zR|&_K=(-B5xvF^b+LDD{nL=@KSL<39N3)BU?>}%dupr1&PU?;||H3>P>zU&-6b$M8s{@5jOC+Ds2BFR!!a{dcTp zh8C|+!`r+mtqNKW|DBdg9g#3-u3P1JhjE!z=5+@fhNW@u^c^%${N>fqy#Cp-h9T|z z*BXOo48|vFSq(}{Rx)OJS_P%=4c1*fE!A`PY?g^Oa;a8QDMj{t!c)~&EnciQ;XnI< zqY020`J-bMl6?7zRY67Tp9U3m)j&E=KxpypM2#W1r{Ju zIKU*(z`zYuqr<=`mcYod0mx}!jR5k2G6{@gK*- nMtT7wlfZ#ZgTe~DWM4fHv8KLZ*U+R`sCEkzKl)gj5&q@hY_5?)@_euSf22N!q0z{yc?Q2YY_Kym8e z5Fvwu2%hQO!{u_psMvL#(bD64NQRTZj^-}DnS22ry9f-;mW=gZvQj}U-ZdMsK&I8^7~DvX`q=ik z`_6m2$ws3QZN>^MN9zsH^_irq|9B!I*`keG1egKL0J+GDWN@5Qi;7vfz#?Eg0+zw! zWh26ppi#h*pi#gmU@Bk~FbXuO0>6OQz)N5NTm`NGN9Lgd-3E+21Wt&^*PQPkP8huh zd;>a7L_nPe*b$Mn3Lg9M_r6s19dKb0Rp7AONHA2j102*viP#bFK}60(=I{{6>WYS# zD)2b=<|hns5!gsp1$>*35h(ElxRF#X(A4JLwboT$#etb*jK#z}f+cAjAM!py#ef+QU|~VyNMc(6d<%P}NJozKFapn6}|c zYcGn_T?_nofdZpuzT8&TA}+s8r530{gO!}|n?7R>-=k5Wg!jBNt~)D~rPk#sV`p>b z2B|gj;Br&8(&RmI1EwcE*bgaR=Xk#0%vANcelQg|-l)l_lDo>?S$ zC`K<@SMBYp}7QXeDo0Tuyf05ibS;?Dr1cxS+3?LM&p0000{C literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_perf_profile_perf.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_perf_profile_perf.png new file mode 100644 index 0000000000000000000000000000000000000000..9834cebbd140fc8b9fced1219e1255636885f455 GIT binary patch literal 915 zcmV;E18n?>P)KLZ*U+R`sCEkzKl)gj5&q@hY_5?)@_euSf22N!q0z{yc?Q2YY_Kym8e z5Fvwu2%hQO!{u_psMvL#(bD64NQRTZj^-}DnS22ry9f-;mW=gZvQj}U-ZdMsK&I8^7~DvX`q=it*uRYvX%(3Um}ycuv;B+de#2HbUtvp}OrOJCcw zz=Hv|8za_OV{zOi@H~RoI4W}r>;tzsu3rYu%bWrqIj*e(hhKLZ*U+R`sCEkzKl)gj5&q@hY_5?)@_euSf22N!q0z{yc?Q2YY_Kym8e z5Fvwu2%hQO!{u_psMvL#(bD64NQRTZj^-}DnS22ry9f-;mW=gZvQj}U-ZdMsK&I8^7~DvX`q=i$3J&3_Tt(yD>PEtR;DFw7?}2EZ$d(# zJVB9EP_!XNVSgAjBN{gIJo7uKtw?FQ4 z<8U}{ce^|HZ1;Ts8Rz`Y?(g?|p6C0#{m#i`vsua+6_h#3UI0~59#Yl+c_Jd2@peD8 zfK&jf0DO@N3WH8gjaP*Eg46<>7BCSsUZ_Q+PH>#8a{zb(c()v#;Avo`h;*px3Sd2O zR=GIA!@v>|>9FhFKySHFpbJwrf%xZxIMS-`0Cq<;+V{9jI6Hr-b9pgob zs)T8M5NH#TR|B5e1M~yuPc#ag23kWlpBKRI6D#!Rx=w3KC0!T_UmpSPOjUG2RWlAR&61J+%&lnI0bwnBEvq~uLo8G+eGAW1V59wD9|Y)U-_8g zdR3hV+^wqLh{&MFWA_2GfE5wuI#Y~VpqLhL0_bo|oKaOb|6T;{0hW3!v=LYX>=cph z5$5|hX%yHaBHfPbYM@S4t30T%T2*Jd{(l*84)AH5iAb@cz(2qTuHPC`)!A0zeebyc zvZ~%?RCrxPhE;Vs@Hp@Xuze(JcOVN4=gZ}|qQEJO?QYZpcdBZw>wde%`HSrOHee>u zV_lypIJ+48DwY8DS!(J=FK`{O&}AL(n->>Vtpgs(H#__yga_)96b1HsEnGwnSx$c| z;I8&Q1DdS$b&FZit^($~(yzof8pIj}4ux1pld8H4m(8}&H4bapSHPTegZdnCQ{d-- zu^ylqnCH^O5p$3a+O6Fp@=L_nKE;t*Cn5@*2pBsCOf!>pJIZhE?+~!JfOX#pT$ZF- zU@$}g{lI)5>&P1acSO{Fg|)+K0>WT6ZVJ={jQwd1je1p`>>;=;xh7{%#JTPTZXc6G zXcSRk25`V5YPzPM#VL1a) z_^+y!z;nP=A&+JXS$MGou*jM7`(%pw%+QHhMuV;hbF8!MF$yvxqQEGkK(iGyTLSt7 zSi0-P9BY&u4blG7)+ZwsqqHSJQA!#4xZ zgtV`m6u88Ez&4-F*8=YWPsLUakFq0F0ko>>4v$lwyak-=s{aRouRS(D8+gZEM2!S- zp9@R{+Eum5b^mYc;5bXz>#a{Pr6X#1()6DrL3hC?elsPg{z8g$Gnwr2!1(5oH j^xNT-0;vGX8UGCc^n)pnZ_3ZY00000NkvXXu0mjfWBeL9 literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_perf_profile.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_perf_profile.png new file mode 100644 index 0000000000000000000000000000000000000000..96ca0befdc486c69f377eec601b04dc11974ddf6 GIT binary patch literal 729 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7OGooCO|{#S9GG!XV7ZFl&wk0|TR3 zrn7TEKt_H^esM;Afr6*AvqC{pep+TuDg#5st+jm{y$%P6IGpcZ^e8}^rLdr4vWCXC zR|&_K=(-B5xvF^b+LDD{nL=@KSL<39N3)BU?>}%dupr1&PU?;||H3>P>zU&-6b$M8s{@5jOC+Ds2BFR!!a{dcTp zh8C|+!`r+mtqNKW|DBdg9g#3-u3P1JhjE!z=5+@fhNW@u^c^%${N>fqy#Cp-h9T|z z*BXOo48|vFSq(}{Rx)OJS_P%=4c1*fE!A`PY?g^Oa;a8QDMj{t!c)~&EnciQ;XnI< zqY020`J-bMl6?7zRY6%@g`I;XCAzlrg$LqpDo z*~xQajBdF5=yjfn`5>depNR=*(&bHg`!7`6|Jr=}x^>My|Ln7@GZX|I81~s8Vwb<8 zec$-;^M_160vrkq>2itn^Y``NZNCXr!So?H-=RW0&$(l!g1`dik_J8lM+FD=7YyPF zO%4rw7Z~*purxBrE?|yn;8bF;a$rBeA_(FpG;x4r4IEiOihW~ zc+p_LaLOWPpnVq@CmS96@gw$HRBQt$6C==s9Sp)OOhAh;3}j#wwm)?GX#36mCgqH3 t94rD2!Y<2BlrpkB(7Xo>#sB}A8J0fsUKZKLqy*$Lc)I$ztaD0e0ssv77qS2V literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_perf_profile_bal.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_perf_profile_bal.png new file mode 100644 index 0000000000000000000000000000000000000000..9804c642939662fcd8dc9dcad7b6c31b6b56dc5b GIT binary patch literal 1951 zcmV;Q2VnS#P)KLZ*U+R`sCEkzKl)gj5&q@hY_5?)@_euSf22N!q0z{yc?Q2YY_Kym8e z5Fvwu2%hQO!{u_psMvL#(bD64NQRTZj^-}DnS22ry9f-;mW=gZvQj}U-ZdMsK&I8^7~DvX`q=iEYwWJo}1xIT3M!%i7y!mqD9^4F99A#Oyu5 zhagXYN6KiJ6T7rUTa}sRNSqfS-XEBrQqeP%9zmFJLGc zgQVMmZ)$-6NjgS0F*5BsV6~(z88tqVjsVX@sRN?)fIomKWE_&_0$-=G6!Dl7F{i-H zazKCJHVQ?ri-FF-*}xC3MDZ1{1=u6$_muN63D_0IfpW!f%9~l3(!+O>x|T3}SKt9) zGLSFxSjT`hz%oe((#n9D?F0sg@SrnJO$?(0o-WbBS-_W0$m9d`@gm?MV859yHM34B z6c2#QIqm9sO%U^k`?8qS7= zCBV!U0gtv03ud-L(mf##7rJ;@i4Hg~#QE+jHoi+_yMXIL9IwBbHH0w!Vpq#4j>(hF zY<-A+{FHogqf@VPr&x; z%4qXpLOjL5V{r?_xk}IfE{MG7TD%ocK~pInX$PPMwS^?ib-fRv!TEk zm&~_H+8DAAqoX7sj`xJeyDbWg142yzmbAm&^_8Ne*W~m0x>zr$qk9^c2+XW+nFEYe zY(j zn%RmN@BVod)~2WkSzE4Vl9^49!T1w_NT$eSalN1y&1_l~jej@rdQ`{D>Uu$o%&eQF zsSz80CIQ~4FGmM7kX=0Dp0qt4qPA0P`2N64RN>XDEE5254Y1wJHUJAGeH=n$%>X7= ztAkl5;3OJ>Ml(AE81M;&7w&!p{%sW+x&T+Y(al(3P_;W&Z|jEkc3Ui{Hyu!u@C0}Q z>KlID&?=%{o(K344?!ND08fBNLP?mAiP`_8x%U7cf;>C{o&b*k lIAzH)5AOk<0FU_a-vH82)!Q1qnPdO}002ovPDHLkV1i3Ba{>SW literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_perf_profile_perf.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_perf_profile_perf.png new file mode 100644 index 0000000000000000000000000000000000000000..8855042bc5038bff7825bdea8a96e844aff1789a GIT binary patch literal 1163 zcmV;61a$j}P)KLZ*U+R`sCEkzKl)gj5&q@hY_5?)@_euSf22N!q0z{yc?Q2YY_Kym8e z5Fvwu2%hQO!{u_psMvL#(bD64NQRTZj^-}DnS22ry9f-;mW=gZvQj}U-ZdMsK&I8^7~DvX`q=i={EkFPS00h`rw#s)*CX>3~TkhT+9$(I2Fkl2=L4W`V0P~x0&4%0L zIh*)+hY^4U0RkWZq%>jHr|nqUm>B_B5CVX+9?+pLm_ZQ3f&c-?0px(NIpC_K%LZRv zNherPI_E}pu1mU!0BO9I^v9^yeR4oLFOBMSC5_1e=^Pu?xxqBF8K*{do*_UpW(GC3 zCGC*|(m9dz%b?C}azHZw}PD{64@9*X)z|Yd{kut+`4k(`!a(lGoe{#T<KLZ*U+R`sCEkzKl)gj5&q@hY_5?)@_euSf22N!q0z{yc?Q2YY_Kym8e z5Fvwu2%hQO!{u_psMvL#(bD64NQRTZj^-}DnS22ry9f-;mW=gZvQj}U-ZdMsK&I8^7~DvX`q=imTnY4&bjB@`@QGR+n$k;5j;AFeY^_10lWb` zyaC26#z#+>S=zeM(YwcAPlhD#0X_tIcmsF?c+?++Qx3R!WX9t49`6A@1bKJ^cmtFk zzW|n&#Q-C9K2^qmYV>p^@OHuXPSoXC_kiV+7PuvXJ%E+L1I7x@m2`RJ+=jC9fGXiX zz^RfRuXF9uGI&5woljM;88|#f`AB*Wc&NbVCF*i4dBAOw&PgHn8(^Lv1B%7BQ!2mh zVQ4HE;3P>`rxlj833$%)faWm-94+a$IqE*>c|ddcJ#dty=X2I?TNtY1AZ(HrHF=Le z`Y|9M))b(8Bn<-VJrBr+TP2-c;QfjSLy5YqiU-^->D+?v`GgNa>9AJPS(ye2v+-t@ z0Q!MFDXTm+7I?sFU~9%Y zdx3?LhBMY%4D2sycS`v`S3Lx6m$U@<67XJzdP^j2&Di^o2NnS9GF1C()eUg5i?=TT zC#9^jLeiZ%o^>ton55KcM@cUN+pEe0Zk4nl^kp9f7ADkr2KZKHYHW5faEzqoIoi3k ziSJli9lITa1FkMpzaZEO!Gx$Ps$_fv*CqGt7LVc(rOg;Hs2ib#M4SIzr4W>9Ae6KoSOsh_ zvxym$KNy_g=m zPr~Zt7lD(_Y;lU-e=u-KFyKpiy2*C$tqKpgx52euV7~@l@FZ{paEF;*0bmNbxC z3QTdwF9VMk(DvSL=K(uNm*D;{@aY6Y{T$d8n%_rfKH;43I!W&rpra|>&I9h3lx8aT zEb!SBa?5~uW_E1k{Dr_Fp}z+TYX5=V9)eQsE^s@RPcXC3CCII!mOHpIa_P*_@i4Hd zp!R>b+YOLqlhZ`fEjKR*&J1QmW_AkjsqmO1sVD|}csKKarzK@sMtG81b}R|kx$+`c zF3#h1DREpk^MI^-Yu36RJv$)`z2ZFUGLP%wGYf zHzH+Db{n-EadZje4+ZLHL6h}6&I4X-qR!kDveAuGZxzITF|$74)NWr3%CnUFCs%$U zM~GV|X=g!gUrZZN#=W6~uKYv_+1FbUejLlbtWyRkk_Q}|qfU?qKE})rO^_XK(e!g! zLHFr64>&4Eoi{?qA5D;bCv^Obq|F8N{`tT;?Q-{48(>zBI^iXR&u3`=`T~?c3Amaz zqSXfYc#b-|G8k~bg5&>+oL-w7<74KoMPa^~O^C|{$KYRX_S6f^NRSQI>i0Gq|IKU} zu%t-k&YU?j@rV3c?E!}Y^E1{NX7tsd=?SvIQt<e-Ut1C#HPun1*JWPdjf3 z!qA7@D@Ab#Jmirklz$>{U#I5W?J&TXlU6rl!Vti|z(EbZ z8I*s0hBj1!2Sjn6nQfAEO9l^^925WhfICwvej2r1a{cX8ZW(w$J>2XDz(&{+I-XSL zdhnZWcc)PPJZedveoBZ=Ek{3OW=A%-zLU{i$>Za=g`|N5ji{HBqEiOwrS{Ur z0S$OSK*q+^2|sgzyBf{!&Fm#cH}uj?258rN!XE)Pn%TZ}*zh}yCg?vv>|D9Jj^Zbn z*$QggVP)9(q=Z-bAjnwuD9YB|%EIHv>z_!Sa=im+X@GC+=p7si-{590x zpqxXOqTM{85e@>jo7sFxzXDzedq8NL$Ohnar~GkcR&E*|P{yCF{H2+FCA3@+ctEgg zdJb@6*_Gdn2b2N#05`kdzs1a^Fq$ZzNQF@5A8!4ID_;hFOhwVId_Z382F?S{>PF?J z$p@7Er;Dco-=xCu|HjH2z#G7$3uZxS24?>+&AkWs5ai(v;0@rB0X-ulBVG&M1H1t| cI)wiZ08ikF2;6UQy8r+H07*qoM6N<$f-F>NW&i*H literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/values/cm_arrays.xml b/packages/SystemUI/res/values/cm_arrays.xml new file mode 100644 index 0000000000000..92ce2788260ef --- /dev/null +++ b/packages/SystemUI/res/values/cm_arrays.xml @@ -0,0 +1,26 @@ + + + + + + + + @drawable/ic_qs_perf_profile_pwrsv + @drawable/ic_qs_perf_profile_bal + @drawable/ic_qs_perf_profile_perf + + + diff --git a/packages/SystemUI/src/com/android/systemui/quicksettings/PerformanceProfileTile.java b/packages/SystemUI/src/com/android/systemui/quicksettings/PerformanceProfileTile.java new file mode 100644 index 0000000000000..d94dadbff737a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/quicksettings/PerformanceProfileTile.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2012 Sven Dawitz for the CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.quicksettings; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.net.Uri; +import android.provider.Settings; +import android.view.View; + +import com.android.systemui.R; +import com.android.systemui.statusbar.phone.QuickSettingsController; + +public class PerformanceProfileTile extends QuickSettingsTile { + + private String[] mEntries; + private TypedArray mTypedArrayDrawables; + private int mCurrentValue; + + private String mPerfProfileDefaultEntry; + private String[] mPerfProfileValues; + + public PerformanceProfileTile(Context context, QuickSettingsController qsc) { + super(context, qsc); + + Resources res = context.getResources(); + mEntries = res.getStringArray(com.android.internal.R.array.perf_profile_entries); + mTypedArrayDrawables = res.obtainTypedArray(R.array.perf_profile_drawables); + + mPerfProfileDefaultEntry = res.getString( + com.android.internal.R.string.config_perf_profile_default_entry); + mPerfProfileValues = res.getStringArray(com.android.internal.R.array.perf_profile_values); + + updateCurrentValue(); + + // Register a callback to detect changes in system properties + qsc.registerObservedContent(Settings.System.getUriFor( + Settings.System.PERFORMANCE_PROFILE), this); + + mOnClick = new View.OnClickListener() { + @Override + public void onClick(View v) { + changeToNextProfile(); + } + }; + } + + @Override + void onPostCreate() { + updateTile(); + super.onPostCreate(); + } + + @Override + public void updateResources() { + updateTile(); + super.updateResources(); + } + + private void changeToNextProfile() { + int current = mCurrentValue + 1; + if (current >= mPerfProfileValues.length) { + current = 0; + } + Settings.System.putString(mContext.getContentResolver(), + Settings.System.PERFORMANCE_PROFILE, mPerfProfileValues[current]); + } + + private void updateCurrentValue() { + String perfProfile = Settings.System.getString(mContext.getContentResolver(), + Settings.System.PERFORMANCE_PROFILE); + if (perfProfile == null) { + perfProfile = mPerfProfileDefaultEntry; + } + + int count = mPerfProfileValues.length; + for (int i = 0; i < count; i++) { + if (mPerfProfileValues[i].equals(perfProfile)) { + mCurrentValue = i; + return; + } + } + + // Something was wrong + mCurrentValue = 0; + } + + private synchronized void updateTile() { + mDrawable = mTypedArrayDrawables.getResourceId(mCurrentValue, -1); + mLabel = mEntries[mCurrentValue]; + } + + + @Override + public void onReceive(Context context, Intent intent) { + updateCurrentValue(); + updateResources(); + } + + @Override + public void onChangeUri(ContentResolver resolver, Uri uri) { + updateCurrentValue(); + updateResources(); + } + +} + diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsController.java index 640d0793398b1..9e930c54cafb7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsController.java @@ -33,6 +33,7 @@ import static com.android.internal.util.cm.QSConstants.TILE_NETWORKMODE; import static com.android.internal.util.cm.QSConstants.TILE_NFC; import static com.android.internal.util.cm.QSConstants.TILE_PROFILE; +import static com.android.internal.util.cm.QSConstants.TILE_PERFORMANCE_PROFILE; import static com.android.internal.util.cm.QSConstants.TILE_QUIETHOURS; import static com.android.internal.util.cm.QSConstants.TILE_RINGER; import static com.android.internal.util.cm.QSConstants.TILE_SCREENTIMEOUT; @@ -55,6 +56,7 @@ import android.net.Uri; import android.os.Handler; import android.os.Message; +import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; @@ -79,6 +81,7 @@ import com.android.systemui.quicksettings.MobileNetworkTypeTile; import com.android.systemui.quicksettings.NetworkAdbTile; import com.android.systemui.quicksettings.NfcTile; +import com.android.systemui.quicksettings.PerformanceProfileTile; import com.android.systemui.quicksettings.PreferencesTile; import com.android.systemui.quicksettings.ProfileTile; import com.android.systemui.quicksettings.QuickSettingsTile; @@ -99,6 +102,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.List; public class QuickSettingsController { private static String TAG = "QuickSettingsController"; @@ -242,6 +246,10 @@ void loadTiles() { if (QSUtils.systemProfilesEnabled(resolver)) { qs = new ProfileTile(mContext, this); } + } else if (tile.equals(TILE_PERFORMANCE_PROFILE)) { + if (QSUtils.deviceSupportsPerformanceProfiles(mContext)) { + qs = new PerformanceProfileTile(mContext, this); + } } else if (tile.equals(TILE_NFC)) { // User cannot add the NFC tile if the device does not support it // No need to check again here diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index af5c3ec56f61c..c7143f2b5e408 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -46,6 +46,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.service.dreams.DreamService; +import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; @@ -111,6 +112,32 @@ public void onChange(boolean selfChange) { } } + private class PerformanceProfileObserver extends ContentObserver { + private final String mPropName; + private final String mPropDef; + + public PerformanceProfileObserver(Context ctx) { + super(null); + mPropName = + ctx.getString(com.android.internal.R.string.config_perf_profile_prop); + mPropDef = + ctx.getString(com.android.internal.R.string.config_perf_profile_default_entry); + } + @Override + public void onChange(boolean selfChange) { + setSystemSetting(); + } + + void setSystemSetting() { + String perfProfile = Settings.System.getString(mContentResolver, + Settings.System.PERFORMANCE_PROFILE); + if (perfProfile == null) { + perfProfile = mPropDef; + } + SystemProperties.set(mPropName, perfProfile); + } + } + @Override public void run() { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, @@ -885,6 +912,16 @@ public void run() { mContentResolver.registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.ADB_PORT), false, new AdbPortObserver()); + if (!TextUtils.isEmpty(context.getString( + com.android.internal.R.string.config_perf_profile_prop))) { + PerformanceProfileObserver observer = new PerformanceProfileObserver(context); + mContentResolver.registerContentObserver( + Settings.System.getUriFor(Settings.System.PERFORMANCE_PROFILE), + false, observer); + + // Sync the system property with the current setting + observer.setSystemSetting(); + } // Before things start rolling, be sure we have decided whether // we are in safe mode. From e7ab084982a4209b0fdf96dc7666588f8180ddcf Mon Sep 17 00:00:00 2001 From: arnau Date: Sat, 2 Nov 2013 12:01:26 +0100 Subject: [PATCH 115/204] SystemUI: CA translations Change-Id: I6ca2d048905be59354233aea315797bb47874181 --- core/res/res/values-ca/cm_strings.xml | 17 +++++++++++++++++ packages/SystemUI/res/values-ca/cm_strings.xml | 2 ++ 2 files changed, 19 insertions(+) diff --git a/core/res/res/values-ca/cm_strings.xml b/core/res/res/values-ca/cm_strings.xml index 73b7ef3241f8c..b841195484e97 100644 --- a/core/res/res/values-ca/cm_strings.xml +++ b/core/res/res/values-ca/cm_strings.xml @@ -124,4 +124,21 @@ Commuta la política SELinux entre el mode imposat o permissiu. Imposa MMAC Commuta la política MMAC entre el mode imposat o permissiu. + Ha fallat. Activa el bloqueig SIM/RUIM. + Codi PUK incorrecte! + El PIN ha fallat! + El PUK ha fallat! + Codi Acceptat! + \nIntents restants : + Targeta invàlida. + La targeta SIM és invàlida. + La SIM/RUIM té un bloqueig personalitzat + La petició USSD està modificada a una nova petició DIAL. + La petició USSD està modificada a una nova petició SS. + La petició USSD està modificada a una nova petició USSD. + La petició SS està modificada a una nova petició DIAL. + La petició SS està modificada a una nova petició USSD. + La petició SS està modificada a una nova petició SS. + SUB:%d : %s. + %s, %s diff --git a/packages/SystemUI/res/values-ca/cm_strings.xml b/packages/SystemUI/res/values-ca/cm_strings.xml index cfc525dbe9164..72e835c237bcf 100644 --- a/packages/SystemUI/res/values-ca/cm_strings.xml +++ b/packages/SystemUI/res/values-ca/cm_strings.xml @@ -55,6 +55,8 @@ LTE apagat Volum Càmera + Desactivat + Activat Extés Normal No es pot connectar a la càmera From dd9a878c03edcaa0b2bed3af72f3bfe2bc2bd26b Mon Sep 17 00:00:00 2001 From: Lingchao Xin Date: Mon, 28 Oct 2013 23:28:05 +0800 Subject: [PATCH 116/204] core: zh_CN translations Change-Id: Iabff7326a7237d28c41787458bc05f41eb77d359 --- core/res/res/values-zh-rCN/cm_strings.xml | 31 +++++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/core/res/res/values-zh-rCN/cm_strings.xml b/core/res/res/values-zh-rCN/cm_strings.xml index 75646a836ab12..3ad355fe1e0c6 100644 --- a/core/res/res/values-zh-rCN/cm_strings.xml +++ b/core/res/res/values-zh-rCN/cm_strings.xml @@ -14,6 +14,21 @@ limitations under the License. --> + 不成功。开启 SIM/RUIM 锁 + 不正确的 PUK 码! + PIN 操作失败! + PUK 操作失败! + 代码已接受! + \n剩余尝试次数: + 无效的卡 + SIM 卡是无效的 + SIM/RUIM 卡已被他人锁定 + USSD 请求已被修改为拨号请求。 + USSD 请求已被修改为 SS 请求。 + USSD 请求已被修改为一个新的 USSD 请求。 + SS 请求已被修改为拨号请求。 + SS 请求已被修改为 USSD 请求。 + SS 请求已被修改为一个新的 SS 请求。 默认 工作 住宅 @@ -47,9 +62,9 @@ 控制 FM 发射器 允许应用控制 FM 发射器。 发送模拟短信 - 允许应用发送模拟短信. - 这允许应用发送短信到受信任的应用. 恶意应用可能连续发送短信, 阻断设备通知系统并扰乱用户. - 正在放电, %d%% + 允许应用发送模拟短信。 + 这允许应用发送短信到受信任的应用。恶意应用可能连续发送短信,阻断设备通知系统并扰乱用户。 + 正在放电,%d%% 没有可移动媒体\u2026 底座 SD 卡 应用程序已被终止 @@ -59,17 +74,17 @@ 屏幕方向已锁定 %s 尚未被安装 启用或禁用隐私防护 - 允许应用更改其他应用是否启用隐私防护. 当一个应用程序运行时启了用隐私防护, 它将不能访问个人数据, 如联系人, 通话记录或者短信. + 允许应用更改其他应用是否启用隐私防护。当一个应用程序运行时启了用隐私防护,它将不能访问个人数据,如联系人,通话记录或者短信。 隐私防护激活 %1$s 将不能访问个人数据 情景模式 取消应用程序通知 - 允许应用取消由其他应用创建的通知. + 允许应用取消由其他应用创建的通知。 拦截向外发送短信 - 允许应用拦截发送短信. 恶意应用可能会使用该功能阻止向外发送短信. + 允许应用拦截发送短信。恶意应用可能会使用该功能阻止向外发送短信。 强制执行 SELinux - 切换 SELinux 策略为强制执行或许可模式. + 切换 SELinux 策略为强制执行或许可模式。 强制执行 MMAC - 切换 MMAC 策略为强制执行或许可模式. + 切换 MMAC 策略为强制执行或许可模式。 From 35b48d37dddf274b341789e412e867eed99c2158 Mon Sep 17 00:00:00 2001 From: Gustavo Date: Mon, 4 Nov 2013 08:44:42 -0200 Subject: [PATCH 117/204] Frameworks_base: PT-BR update translations Change-Id: Id545b9f4566303799c2b1264c726de80984f2787 --- core/res/res/values-pt/cm_strings.xml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/core/res/res/values-pt/cm_strings.xml b/core/res/res/values-pt/cm_strings.xml index 82601f4e2ec94..5a16b2c3b889d 100644 --- a/core/res/res/values-pt/cm_strings.xml +++ b/core/res/res/values-pt/cm_strings.xml @@ -128,4 +128,21 @@ Economia Balanceado Performance - + Malsucedido. Ativar Bloqueio SIM/RUIM. + Código PUK incorreto! + Falha na operação PIN! + Falha na operação PUK! + Código aceito! + \nTentativas Restantes : + Cartão inválido. + Cartão SIM é Inválido. + SIM/RUIM é bloqueado por Perso + Requisição USSD foi modificado para requição DIAL. + Requisição USSD foi modificado para requisição SS. + Requisição USSD foi modificado para uma nova requisição USSD. + Requisição SS foi modificado para requisição DIAL. + Requisição SS foi modificado para requisição USSD. + Requisição SS foi modificado para uma nova requisição SS. + ASS:%d : %s. + %s, %s + \ No newline at end of file From eae4d031bcf535d6d1b6713e3cc0860df6f0b040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20J=C3=B8rgensen?= Date: Mon, 4 Nov 2013 21:52:00 +0100 Subject: [PATCH 118/204] frameworks_base: DA translation Change-Id: I56c4df19601b11aae9508667646ac12ed248c212 --- core/res/res/values-da/cm_strings.xml | 20 ++++++++ .../InputDevices/res/values-da/cm_strings.xml | 50 +++++++++++++++++++ .../SystemUI/res/values-da/cm_strings.xml | 2 + 3 files changed, 72 insertions(+) create mode 100644 packages/InputDevices/res/values-da/cm_strings.xml diff --git a/core/res/res/values-da/cm_strings.xml b/core/res/res/values-da/cm_strings.xml index cd54dd60daf49..222860b51c02f 100644 --- a/core/res/res/values-da/cm_strings.xml +++ b/core/res/res/values-da/cm_strings.xml @@ -46,6 +46,8 @@ Tillader app\'en at kontrollere FM-modtageren. kontrollér FM-modtager Tillader app\'en at kontrollere FM-senderen. + send imiterede SMS-beskeder + Tillader at appen sender imiterede SMS-beskeder. Dette tillader en app at sende SMS-beskeder til betroede apps. Ondsindede apps kan sende beskeder hele tiden, hvilket blokerer enhedens meddelelsessystem og forstyrrer brugeren. Aflader, %d%% Dock SD-kort App lukket @@ -123,4 +125,22 @@ Slå håndhævning af SELinux-politikker eller tolerant tilstand til og fra. Håndhæv MMAC Slå håndhævning af MMAC-politikker eller tolerant tilstand til og fra. + Mislykkedes. Aktivér SIM/RUIM-Lås. + Forkert PUK-kode! + PIN-betjening mislykkedes! + PUK-betjening mislykkedes! + Kode Accepteret! + \nResterende Forsøg : + Ugyldigt kort. + SIM-kortet er ugyldigt. + SIM/RUIM er Perso-låst + Intet flytbart medie tilgængeligt\u2026 + USSD-anmodning er ændret til en DIAL-anmodning. + USSD-anmodning er ændret til en SS-anmodning. + USSD-anmodning er ændret til en ny USSD-anmodning. + SS-anmodning er ændret til en DIAL-anmodning. + SS-anmodning er ændret til en USSD-anmodning. + SS-anmodning er ændret til en ny SS-anmodning. + SUB:%d : %s. + %s, %s diff --git a/packages/InputDevices/res/values-da/cm_strings.xml b/packages/InputDevices/res/values-da/cm_strings.xml new file mode 100644 index 0000000000000..8e40caba2547f --- /dev/null +++ b/packages/InputDevices/res/values-da/cm_strings.xml @@ -0,0 +1,50 @@ + + + + Inputenheder + Android-Tastatur + Engelsk (UK) + Engelsk (USA) + Engelsk (USA), Colemak + Engelsk (USA), Dvorak + Tysk + Fransk + Fransk (Canada) + Russisk + Russisk, Mac + Spansk + Fransk (Schweiz) + Tysk (Schweiz) + Belgisk + Bulgarsk + Italiensk + Dansk + Norsk + Svensk + Finsk + Kroatisk + Tjekkisk + Estisk + Ungarsk + Islandsk + Portugisisk + Slovakisk + Slovensk + Tyrkisk + Ukrainsk + Østarmensk + diff --git a/packages/SystemUI/res/values-da/cm_strings.xml b/packages/SystemUI/res/values-da/cm_strings.xml index 98f3056c7eaf8..684e12644fde5 100644 --- a/packages/SystemUI/res/values-da/cm_strings.xml +++ b/packages/SystemUI/res/values-da/cm_strings.xml @@ -53,6 +53,8 @@ LTE fra Lydstyrke Kamera + Deaktiveret + Aktiveret Udvidet Normal Kan ikke forbinde til kameraet From 2039adde6e494f71a8c1b6cfc4f3b497b5c7c43e Mon Sep 17 00:00:00 2001 From: Jorge Ruesga Date: Tue, 5 Nov 2013 00:14:00 +0100 Subject: [PATCH 119/204] PhoneWindowPolicy: Fix NPE race condition by excessive screen on delay When screen on has an excessive delay mTopFullscreenOpaqueWindowState could not be initialized. This derives in a NPE from a Power key press. If mTopFullscreenOpaqueWindowState = null then PREVENT_POWER_KEY can be safelly ignored Change-Id: I04ce5d88f6f9abf02b2bbcdce4a2acad2f6451fa Signed-off-by: Jorge Ruesga --- .../com/android/internal/policy/impl/PhoneWindowManager.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index ecd94895116d8..1f14531ca392a 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -4446,8 +4446,9 @@ public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean i } case KeyEvent.KEYCODE_POWER: { - if ((mTopFullscreenOpaqueWindowState.getAttrs().flags - & WindowManager.LayoutParams.PREVENT_POWER_KEY) != 0){ + if ((mTopFullscreenOpaqueWindowState != null && + (mTopFullscreenOpaqueWindowState.getAttrs().flags + & WindowManager.LayoutParams.PREVENT_POWER_KEY) != 0)) { return result; } result &= ~ACTION_PASS_TO_USER; From 3a52425c9818db485132195e8a73969063c93cdb Mon Sep 17 00:00:00 2001 From: Gustavo Date: Tue, 5 Nov 2013 11:33:05 -0200 Subject: [PATCH 120/204] Frameworks_base: PT-BR update translations Change-Id: I73b77dc2485704ee779f8570f3c77e7eb9c64a04 --- core/res/res/values-pt/cm_arrays.xml | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 core/res/res/values-pt/cm_arrays.xml diff --git a/core/res/res/values-pt/cm_arrays.xml b/core/res/res/values-pt/cm_arrays.xml new file mode 100644 index 0000000000000..ea81364a20d97 --- /dev/null +++ b/core/res/res/values-pt/cm_arrays.xml @@ -0,0 +1,55 @@ + + + + + Tentando acessar localização + Tentando acessar localização + Tentando acessar localização + Tentando usar vibração + Tentando ler contatos + Tentando modificar contatos + Tentando ler registros de chamadas + Tentando modificar registro de chamadas + Tentando ler calendário + Tentando modificar calendário + Tentando acessar localizaçãon + Tentando enviar notificação + Tentando acessar localização + Tentando realizar chamadal + Tentando ler SMS/MMS + Tentando escrever/modificar SMS/MMS + Tentando receber SMS/MMS + Tentando receber SMS/MMS + Tentando receber SMS/MMS + Tentando receber SMS/MMS + Tentando enviar SMS/MMS + Tentando ler SMS/MMS + Tentando escrever/modificar SMS/MMS + Tentando modificar configurações + Tentando desenhar no topo + Tentando acessar notificações + Tentando acessar Câmera + Tentando gravar áudio + Tentando reproduzir áudio + Tentando ler área de transferência + Tentando modificar área de transferência + Tentando desligar/ligar Wi-Fi + Tentando ligar/desligar Bluetooth + Tentando ligar/desligar dados + Tentando agendar despertador do dispositivo + + \ No newline at end of file From 2ba37628b0ad2ac0a45f205f43e376a60d98aa22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20J=C3=B8rgensen?= Date: Tue, 5 Nov 2013 19:44:10 +0100 Subject: [PATCH 121/204] frameworks_base: DA translation Change-Id: I1f8fc6f36d110ba0d8bad477dc2329fe7236d101 --- core/res/res/values-da/cm_strings.xml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/res/res/values-da/cm_strings.xml b/core/res/res/values-da/cm_strings.xml index 222860b51c02f..822dcedcace12 100644 --- a/core/res/res/values-da/cm_strings.xml +++ b/core/res/res/values-da/cm_strings.xml @@ -118,9 +118,7 @@ annuller app-underretninger Tillader app\'en at annullere underretninger, oprettet af andre apps. blokér udgående SMS - Tillader app\'en at - blokere en udgående SMS. - Ondsindede apps kan muligvis bruge dette til at forhindre udgående SMS-beskeder. + Tillader app\'en at blokere en udgående SMS. Ondsindede apps kan muligvis bruge dette til at forhindre udgående SMS-beskeder. Håndhæv SELinux Slå håndhævning af SELinux-politikker eller tolerant tilstand til og fra. Håndhæv MMAC @@ -143,4 +141,7 @@ SS-anmodning er ændret til en ny SS-anmodning. SUB:%d : %s. %s, %s + Strømbesparelse + Balanceret + Høj ydeevne From 3583f78e9358fc59e4d5481b43425f93dc01d37e Mon Sep 17 00:00:00 2001 From: Eddy Witkamp Date: Mon, 4 Nov 2013 23:35:00 +0100 Subject: [PATCH 122/204] Framework: NL translation ps1: QS performance profiles tile ps2: move CAF strings to bottom Change-Id: I63f73a78b659cc3da8c39583d9f4f2627fb3fcf4 --- core/res/res/values-nl/cm_strings.xml | 40 +++++++++++++++------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/core/res/res/values-nl/cm_strings.xml b/core/res/res/values-nl/cm_strings.xml index fe5bd662329fc..17b9f2a1a6e24 100644 --- a/core/res/res/values-nl/cm_strings.xml +++ b/core/res/res/values-nl/cm_strings.xml @@ -15,24 +15,6 @@ limitations under the License. --> - Mislukt. SIM/RUIM-vergrendeling inschakelen. - Pukcode ongeldig - PIN-bewerking mislukt - PUK-bewerking mislukt - Code correct - \nResterende pogingen: - Kaart ongeldig - Simkaart is ongeldig - SIM/RUIM bevat Perso-vergrendeling. - USSD-verzoek veranderd naar DIAL-verzoek. - USSD-verzoek veranderd naar SS-verzoek. - USSD-verzoek veranderd naar nieuw USSD-verzoek. - SS-verzoek veranderd naar DIAL-verzoek. - SS-verzoek veranderd naar USSD-verzoek. - SS-verzoek veranderd naar nieuw SS-verzoek. - ABON.:%d : %s. - %s, %s - Standaard Zakelijk Thuis @@ -90,4 +72,26 @@ Wisselen tussen SELinux-beleid afdwingen of tolerante stand. MMAC afdwingen Wisselen tussen MMAC-beleid afdwingen of tolerante stand. + Energiebesparing + Gebalanceerd + Prestaties + + + Mislukt. SIM/RUIM-vergrendeling inschakelen. + Pukcode ongeldig + PIN-bewerking mislukt + PUK-bewerking mislukt + Code correct + \nResterende pogingen: + Kaart ongeldig + Simkaart is ongeldig + SIM/RUIM bevat Perso-vergrendeling. + USSD-verzoek veranderd naar DIAL-verzoek. + USSD-verzoek veranderd naar SS-verzoek. + USSD-verzoek veranderd naar nieuw USSD-verzoek. + SS-verzoek veranderd naar DIAL-verzoek. + SS-verzoek veranderd naar USSD-verzoek. + SS-verzoek veranderd naar nieuw SS-verzoek. + ABON.:%d : %s. + %s, %s From 7ab6784e7ad24e8ac0326d1955f101c0aa37c775 Mon Sep 17 00:00:00 2001 From: Veeti Paananen Date: Wed, 6 Nov 2013 00:55:06 +0200 Subject: [PATCH 123/204] Don't show phone unlock targets for devices without voice (1/2) Add a separate list of default lockscreen unlock targets for devices without voice capability. Change-Id: I59d6711e74c3bf48e6453a9530fa88f28b25b78e --- packages/SettingsProvider/res/values/defaults.xml | 3 ++- .../com/android/providers/settings/DatabaseHelper.java | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml index 930132812fecd..bd84a4387eda0 100644 --- a/packages/SettingsProvider/res/values/defaults.xml +++ b/packages/SettingsProvider/res/values/defaults.xml @@ -190,8 +190,9 @@ 2. Left --> 0 - + + 0 diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 75f25f4973242..91fa9d7721740 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -2032,8 +2032,14 @@ private void loadSystemSettings(SQLiteDatabase db) { loadIntegerSetting(stmt, Settings.System.QS_QUICK_PULLDOWN, R.integer.def_qs_quick_pulldown); - loadStringSetting(stmt, Settings.System.LOCKSCREEN_TARGETS, - R.string.def_lockscreen_targets); + if (mContext.getResources() + .getBoolean(com.android.internal.R.bool.config_voice_capable)) { + loadStringSetting(stmt, Settings.System.LOCKSCREEN_TARGETS, + R.string.def_lockscreen_targets); + } else { + loadStringSetting(stmt, Settings.System.LOCKSCREEN_TARGETS, + R.string.def_lockscreen_targets_no_telephony); + } loadIntegerSetting(stmt, Settings.System.UI_FORCE_OVERFLOW_BUTTON, R.integer.def_force_overflow_button); From 6f4da510ffa0e385d7f9f77b935975cec4468d52 Mon Sep 17 00:00:00 2001 From: Vladimir Belkov Date: Tue, 5 Nov 2013 23:30:03 +0400 Subject: [PATCH 124/204] core: RU translation Change-Id: Ieffc693827aea4fc7a0e036e3cbd78924c691acb --- core/res/res/values-ru/cm_strings.xml | 29 ++++++++++++++++----------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/core/res/res/values-ru/cm_strings.xml b/core/res/res/values-ru/cm_strings.xml index c1d8930b1e409..4f5156e1ce1c9 100644 --- a/core/res/res/values-ru/cm_strings.xml +++ b/core/res/res/values-ru/cm_strings.xml @@ -45,36 +45,41 @@ Поворот экрана разблокирован Поворот экрана заблокирован %s не установлено - - Включение или выключение режима инкогнито Приложение может выбрать, будет ли другое приложение работать в режиме инкогнито. Когда приложение запущено в режиме инкогнито, оно не получает доступ к персональным данным, таким как контакты, сообщения или журнал звонков. Режим инкогнито активен %1$s не сможет получать доступ к персональным данным - - Профили - - Не выбран - Отключение уведомлений Разрешить приложению отключать уведомления, созданные другими приложениями. - Перехват исходящих SMS Разрешить приложению перехватывать исходящие SMS. Вредоносные приложения смогут использовать это, чтобы препятствовать отправке SMS-сообщений. - Показ фиктивных SMS-сообщений Разрешить приложению показывать фиктивные SMS. Вредоносные приложения могут посылать сообщения циклически, блокируя систему уведомлений и раздражая пользователя. - Отсутствует внешний накопитель - Переключение режимов SELinux Переключать принудительный и разрешающий режимы политики SELinux. Переключение режимов MMAC Переключать принудительный и разрешающий режимы политики MMAC. - Экономия энергии Сбалансированный Высокая производительность + Карта недействительна. + SIM-карта недействительна. + Неудачно. Включите блокировку SIM/RUIM-карты. + Неверный PUK-код + Разблокировка PIN-кодом не удалась + Разблокировка PUK-кодом не удалась + Код принят + \nОсталось попыток: + USSD-запрос преобразован в DIAL-запрос. + USSD-запрос преобразован в SS-запрос. + USSD-запрос преобразован в новый USSD-запрос. + SS-запрос преобразован в DIAL-запрос. + SS-запрос преобразован в USSD-запрос. + SS-запрос преобразован в новый SS-запрос. + ПОДП.:%d : %s. + %s, %s + SIM/RUIM-карта заблокирована From 00992821dd7c4575652070e0c25fd9c4b786df7a Mon Sep 17 00:00:00 2001 From: Ted Lundwall Date: Wed, 6 Nov 2013 17:21:36 +0100 Subject: [PATCH 125/204] Base: SV translations Change-Id: I76e25154e1cfa1b55cdb2bdb5c131dbf691aecb6 --- packages/SystemUI/res/values-sv/cm_strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/SystemUI/res/values-sv/cm_strings.xml b/packages/SystemUI/res/values-sv/cm_strings.xml index fa57f66f7ad37..cc8c77351775e 100644 --- a/packages/SystemUI/res/values-sv/cm_strings.xml +++ b/packages/SystemUI/res/values-sv/cm_strings.xml @@ -51,6 +51,8 @@ Expanderat Normalt Kan inte kontakta kamera + Inaktiverad + Aktiverad Välj åtgärd att tilldela Hemknapp Tidigareknapp From c1d48c185045439a98e5be4df436b3c0952b14c6 Mon Sep 17 00:00:00 2001 From: MatoDroid Date: Wed, 6 Nov 2013 17:32:59 +0100 Subject: [PATCH 126/204] core: SK translations Change-Id: Ic9522a57a058d6b2afee194d3780d25939bfa492 --- core/res/res/values-sk/cm_strings.xml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/core/res/res/values-sk/cm_strings.xml b/core/res/res/values-sk/cm_strings.xml index 648afc2ff9b34..2ad0a461d4436 100644 --- a/core/res/res/values-sk/cm_strings.xml +++ b/core/res/res/values-sk/cm_strings.xml @@ -72,6 +72,23 @@ posielať falošné SMS správy Povolí aplikácii odosielať falošné SMS správy. Toto povolenie umožňuje aplikácii posielať SMS do dôveryhodných aplikácií. Škodlivé aplikácie môžu posielať správy nepretržite, blokovať oznamovací systém zariadenia a vyrušovať užívateľa. Nie je dostupné žiadne vymeniteľné médium\u2026 + Neúspešné. Povoľte zámok SIM/RUIM. + Nesprávny kód PUK! + Operácia PIN zlyhala! + Operácia PUK zlyhala! + Kód prijatý! + \nZostáva pokusov: + Neplatná karta. + Karta SIM je neplatná. + Karta SIM/RUIM je zamknutá + Požiadavka USSD je upravená na požiadavku DIAL. + Požiadavka USSD je upravená na požiadavku SS. + Požiadavka USSD je upravená na novú požiadavku USSD. + Požiadavka SS je upravená na požiadavku DIAL. + Požiadavka SS je upravená na požiadavku USSD. + Požiadavka SS je upravená na novú požiadavku SS. + Odber %d: %s. + %s, %s Úsporný Vyvážený Výkonný From 87b20f5de32531d5b8bfce5cfcc90a244ef3488c Mon Sep 17 00:00:00 2001 From: Ethan Chen Date: Wed, 6 Nov 2013 11:26:33 -0800 Subject: [PATCH 127/204] Move android-4.3_r3.1 config options Change-Id: I9c51a13236795c18903e001a4070b7e8959b7278 --- core/res/res/values/config.xml | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index f539293e6b24b..8d784d8a8d53c 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -782,19 +782,6 @@ 8.8.8.8 - - - - - - - - http://google.com - @@ -1160,6 +1147,21 @@ com.android.inputmethod.latin + + + + + + + + + + http://google.com + From 5a75a684ee97e8f4596c3a6a598bf84c0e5d6938 Mon Sep 17 00:00:00 2001 From: Mahesh A Saptasagar Date: Wed, 2 Oct 2013 16:46:26 +0530 Subject: [PATCH 128/204] p2p: Flush the p2p scan result on group remove event Flush out p2p scan results on receiving group removal event. p2p scan window will be updated on next p2p scan. Change-Id: I3bcfed355574478bda2cac688b7df956c2701683 CRs-Fixed: 504022 --- wifi/java/android/net/wifi/p2p/WifiP2pService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java index 9e27a9984a188..2063dbf9439e0 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -1791,6 +1791,7 @@ public boolean processMessage(Message message) { if (DBG) logd(getName() + " remove group"); if (mWifiNative.p2pGroupRemove(mGroup.getInterface())) { transitionTo(mOngoingGroupRemovalState); + mWifiNative.p2pFlush(); replyToMessage(message, WifiP2pManager.REMOVE_GROUP_SUCCEEDED); } else { handleGroupRemoved(); From 750d44e6fbfae21690bdd35008aafdfd339fbece Mon Sep 17 00:00:00 2001 From: Deepthi Gowri Date: Tue, 9 Jul 2013 10:37:58 +0530 Subject: [PATCH 129/204] Wifi: wifi not connecting, once the APN gets disabled state APNs are disabled on select network and they are enabled on receiving connected event. But forgetting an APN before the connected event is received, will result all the remaining APN to be in disabled state and they never connect. So, Enabling all the disabled APN on forget network will help to connect automatically to a saved APN. Change-Id: I6ac5e9856d6ec0b72c089b159206abd2de98e6a3 CRs-fixed: 496165 --- wifi/java/android/net/wifi/WifiConfigStore.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java index cef59133eabb4..87dfd0bef26e4 100644 --- a/wifi/java/android/net/wifi/WifiConfigStore.java +++ b/wifi/java/android/net/wifi/WifiConfigStore.java @@ -296,6 +296,15 @@ void updateStatus(int netId, DetailedState state) { */ boolean forgetNetwork(int netId) { if (mWifiNative.removeNetwork(netId)) { + for(WifiConfiguration config : mConfiguredNetworks.values()) { + if(config != null && config.status == Status.DISABLED) { + if(mWifiNative.enableNetwork(config.networkId, false)) { + config.status = Status.ENABLED; + } else { + loge("Enable network failed on " + config.networkId); + } + } + } mWifiNative.saveConfig(); removeConfigAndSendBroadcastIfNeeded(netId); return true; From 1f7e4adc599c8ed3528cc0bee5d792a3cea88687 Mon Sep 17 00:00:00 2001 From: Mahesh A Saptasagar Date: Fri, 18 Oct 2013 14:34:40 +0530 Subject: [PATCH 130/204] Revert "p2p: Fix for discovery failure until AP is connected in WFD client" This reverts commit 738434a7df1cf7d0aada02e7905bdb4a51b5d3d6. Change-Id: I4c1f061aa26077134029527dfc3e55112fed5038 CRs-Fixed: 532138 --- .../android/net/wifi/p2p/WifiP2pService.java | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java index 2063dbf9439e0..53700691adbec 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -975,11 +975,15 @@ public boolean processMessage(Message message) { boolean blocked = (message.arg1 == ENABLED ? true : false); if (mDiscoveryBlocked == blocked) break; mDiscoveryBlocked = blocked; - if (blocked) { - if (mDiscoveryStarted) { - mWifiNative.p2pStopFind(); - } + if (blocked && mDiscoveryStarted) { + mWifiNative.p2pStopFind(); mDiscoveryPostponed = true; + } + if (!blocked && mDiscoveryPostponed) { + mDiscoveryPostponed = false; + mWifiNative.p2pFind(DISCOVER_TIMEOUT_S); + } + if (blocked) { try { StateMachine m = (StateMachine)message.obj; m.sendMessage(message.arg2); @@ -987,17 +991,12 @@ public boolean processMessage(Message message) { loge("unable to send BLOCK_DISCOVERY response: " + e); } } - if (!blocked && mDiscoveryPostponed) { - mDiscoveryPostponed = false; - mWifiNative.p2pFind(DISCOVER_TIMEOUT_S); - } break; case WifiP2pManager.DISCOVER_PEERS: if (mDiscoveryBlocked) { - /* do not send discovery failure to apps. - since discovery is postponed and not failed */ - loge("P2P_FIND is deffered"); - break; + replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, + WifiP2pManager.BUSY); + break; } // do not send service discovery request while normal find operation. clearSupplicantServiceRequest(); From 6cecdf6872ed4bc76d402e7bfec9b3ca167e0c12 Mon Sep 17 00:00:00 2001 From: Mahesh A Saptasagar Date: Fri, 18 Oct 2013 20:30:56 +0530 Subject: [PATCH 131/204] p2p:Fix for discovery failure until STA is connected to AP. The station when connecting to AP (wifi state is either connecting or obtaining ip address) shall stop the already issued p2p_find on the DHCP start and start the same after the DHCP handshake. p2p service manager shall return a failure for any p2p_find operation during these period resulting in a discover failure. Address this by deferring the p2p_find issued during this period (set mDiscoveryPostponed to true) rather than returning a failure. Change-Id: I40b2017bf126fd0d543ada8853223402cda63e9d CRs-Fixed: 532138 --- wifi/java/android/net/wifi/p2p/WifiP2pService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java index 53700691adbec..873279ad3747d 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -994,8 +994,10 @@ public boolean processMessage(Message message) { break; case WifiP2pManager.DISCOVER_PEERS: if (mDiscoveryBlocked) { - replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, - WifiP2pManager.BUSY); + /* do not send discovery failure to apps. + since discovery is postponed and not failed */ + mDiscoveryPostponed = true; + logi("P2P_FIND is deffered"); break; } // do not send service discovery request while normal find operation. From cae7ab1132f19d234dfad14c4e6a0ee997443aba Mon Sep 17 00:00:00 2001 From: Sameer Thalappil Date: Wed, 16 Oct 2013 14:41:21 -0700 Subject: [PATCH 132/204] Clear the scan list when an empty list is received When the framework receives an empty scan list from supplicant, it does not clear the local list. So the UI will continue to show the previous scan list even when there are no APs around. So clear the local list, when an empty list is received. CRs-Fixed: 552212 Change-Id: I8715bc31ce0df7bd54c96fcf7d7b73592429f12a --- wifi/java/android/net/wifi/WifiStateMachine.java | 1 + 1 file changed, 1 insertion(+) diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java index d2fde34884339..b2c54e14c444f 100644 --- a/wifi/java/android/net/wifi/WifiStateMachine.java +++ b/wifi/java/android/net/wifi/WifiStateMachine.java @@ -1555,6 +1555,7 @@ private void setScanResults() { scanResults = scanResultsBuf.toString(); if (TextUtils.isEmpty(scanResults)) { + mScanResults.clear(); return; } synchronized(mScanResultCache) { From 4d03a8ca3b1a3bd2ff54133524e516dec8e2d2c7 Mon Sep 17 00:00:00 2001 From: Wink Saville Date: Sat, 14 Sep 2013 09:04:53 -0700 Subject: [PATCH 133/204] Tighten condition for calling checkMobileProvisioning. Add the condition that the connected network needs to be TYPE_MOBILE. This eliminates checking on connecting to secondary networks like FOTA, MMS, SUPL ... This reduces unnecessary attempts to bring up multiple connections at the same time. Especially in the light of the trouble we're having with HFA on Sprint, where we don't want to connect to any other network until HFA has completed. Bug: 10758001 Change-Id: Id294536b70304a51de4752bc1a4ffac734f10f1a --- services/java/com/android/server/ConnectivityService.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 9d1b51402e0c9..12476de7b6091 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -2819,8 +2819,11 @@ public void handleMessage(Message msg) { if (ConnectivityManager.isNetworkTypeMobile(info.getType()) && (0 != Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0)) - && ((state == NetworkInfo.State.CONNECTED) - || info.isConnectedToProvisioningNetwork())) { + && (((state == NetworkInfo.State.CONNECTED) + && (info.getType() == ConnectivityManager.TYPE_MOBILE)) + || info.isConnectedToProvisioningNetwork())) { + log("ConnectivityChange checkMobileProvisioning for" + + " TYPE_MOBILE or ProvisioningNetwork"); checkMobileProvisioning(CheckMp.MAX_TIMEOUT_MS); } From 96015dfd76eee7088778fabf37d7aa94f71fa82b Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 8 Oct 2013 10:41:25 +0900 Subject: [PATCH 134/204] Fix captive portal detection on IPv6 networks. Currently the captive portal check URL is generated by concatenating scheme, "://", IP address, and port. This breaks for IPv6 because IPv6 addresses in URLs must be enclosed in square brackets (e.g., http://2001:db8::1/generate_204 is invalid; should he http://[2001:db8::1]/generate_204 instead). The resulting MalformedURLException causes isMobileOk to report that there is no captive portal, even if there is one. Fortunately the three-arg URL constructor already knows how to construct URLs with IPv6 addresses. Use that instead of generating the URL ourselves. Bug: 10801896 Change-Id: I02605ef62f493a34f25bb405ef02b111543a76fd --- .../java/com/android/server/ConnectivityService.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 12476de7b6091..3305000add552 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -4010,6 +4010,9 @@ private synchronized Integer isMobileOk(Params params) { addrTried ++) { // Choose the address at random but make sure its type is supported + // TODO: This doesn't work 100% of the time, because we may end up + // trying the same invalid address more than once and ignoring one + // of the valid addresses. InetAddress hostAddr = addresses[rand.nextInt(addresses.length)]; if (((hostAddr instanceof Inet4Address) && linkHasIpv4) || ((hostAddr instanceof Inet6Address) && linkHasIpv6)) { @@ -4034,10 +4037,8 @@ private synchronized Integer isMobileOk(Params params) { } // Rewrite the url to have numeric address to use the specific route. - // I also set the "Connection" to "Close" as by default "Keep-Alive" - // is used which is useless in this case. - URL newUrl = new URL(orgUri.getScheme() + "://" - + hostAddr.getHostAddress() + orgUri.getPath()); + URL newUrl = new URL(orgUri.getScheme(), + hostAddr.getHostAddress(), orgUri.getPath()); log("isMobileOk: newUrl=" + newUrl); HttpURLConnection urlConn = null; @@ -4050,6 +4051,8 @@ private synchronized Integer isMobileOk(Params params) { urlConn.setReadTimeout(SOCKET_TIMEOUT_MS); urlConn.setUseCaches(false); urlConn.setAllowUserInteraction(false); + // Set the "Connection" to "Close" as by default "Keep-Alive" + // is used which is useless in this case. urlConn.setRequestProperty("Connection", "close"); int responseCode = urlConn.getResponseCode(); if (responseCode == 204) { From d8c29bda47cac493e320ff907b0249198e9f31b1 Mon Sep 17 00:00:00 2001 From: Mahesh A Saptasagar Date: Mon, 28 Oct 2013 20:15:38 +0530 Subject: [PATCH 135/204] frameworks/base: Free BufferedReader class object Free the BufferedReader class object explicitly. Change-Id: I6a9f19e0334e1985652852447c545fa2227a04b5 CRs-Fixed: 564739 --- services/java/com/android/server/RegulatoryObserver.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/java/com/android/server/RegulatoryObserver.java b/services/java/com/android/server/RegulatoryObserver.java index c4fb9ca51351d..8413d7673e1a3 100644 --- a/services/java/com/android/server/RegulatoryObserver.java +++ b/services/java/com/android/server/RegulatoryObserver.java @@ -93,6 +93,9 @@ private final void init() { run_crda(); } } + if (uevent_buf != null) { + uevent_buf.close(); + } } catch (Exception e) { Slog.e(TAG, "This kernel may not have CRDA support." , e); } From 1c99da840453411b6dbf01e221a1e48f2629dd2c Mon Sep 17 00:00:00 2001 From: Wink Saville Date: Fri, 6 Sep 2013 09:53:08 -0700 Subject: [PATCH 136/204] Tighten test for warm sim and add more debug. - Require a non-204 response multiple times before declaring a redirected error and hence a warm sim. - If there is no connection or dns don't declare its a warm-sim. - Add printing of the http headers to try to get more information if we still get a false positive result. Bug: 9972012 Change-Id: Ic115685cdbbe39c2b4de88b128eaf8d2ea96b45c --- .../android/server/ConnectivityService.java | 66 ++++++++++++------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 3305000add552..d844f9f4a6277 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -144,6 +144,7 @@ import java.util.GregorianCalendar; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Random; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -3678,39 +3679,41 @@ private boolean isMobileDataStateTrackerReady() { /** * No connection was possible to the network. + * This is NOT a warm sim. */ - public static final int CMP_RESULT_CODE_NO_CONNECTION = 0; + private static final int CMP_RESULT_CODE_NO_CONNECTION = 0; /** * A connection was made to the internet, all is well. + * This is NOT a warm sim. */ - public static final int CMP_RESULT_CODE_CONNECTABLE = 1; + private static final int CMP_RESULT_CODE_CONNECTABLE = 1; /** - * A connection was made but there was a redirection, we appear to be in walled garden. - * This is an indication of a warm sim on a mobile network. + * A connection was made but no dns server was available to resolve a name to address. + * This is NOT a warm sim since provisioning network is supported. */ - public static final int CMP_RESULT_CODE_REDIRECTED = 2; + private static final int CMP_RESULT_CODE_NO_DNS = 2; /** - * A connection was made but no dns server was available to resolve a name to address. - * This is an indication of a warm sim on a mobile network. + * A connection was made but could not open a TCP connection. + * This is NOT a warm sim since provisioning network is supported. */ - public static final int CMP_RESULT_CODE_NO_DNS = 3; + private static final int CMP_RESULT_CODE_NO_TCP_CONNECTION = 3; /** - * A connection was made but could not open a TCP connection. - * This is an indication of a warm sim on a mobile network. + * A connection was made but there was a redirection, we appear to be in walled garden. + * This is an indication of a warm sim on a mobile network such as T-Mobile. */ - public static final int CMP_RESULT_CODE_NO_TCP_CONNECTION = 4; + private static final int CMP_RESULT_CODE_REDIRECTED = 4; /** * The mobile network is a provisioning network. - * This is an indication of a warm sim on a mobile network. + * This is an indication of a warm sim on a mobile network such as AT&T. */ - public static final int CMP_RESULT_CODE_PROVISIONING_NETWORK = 5; + private static final int CMP_RESULT_CODE_PROVISIONING_NETWORK = 5; - AtomicBoolean mIsCheckingMobileProvisioning = new AtomicBoolean(false); + private AtomicBoolean mIsCheckingMobileProvisioning = new AtomicBoolean(false); @Override public int checkMobileProvisioning(int suggestedTimeOutMs) { @@ -3785,7 +3788,9 @@ void onComplete(Integer result) { mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI].getNetworkInfo(); switch(result) { case CMP_RESULT_CODE_CONNECTABLE: - case CMP_RESULT_CODE_NO_CONNECTION: { + case CMP_RESULT_CODE_NO_CONNECTION: + case CMP_RESULT_CODE_NO_DNS: + case CMP_RESULT_CODE_NO_TCP_CONNECTION: { if (DBG) log("CheckMp.onComplete: ignore, connected or no connection"); break; } @@ -3804,8 +3809,7 @@ void onComplete(Integer result) { } break; } - case CMP_RESULT_CODE_NO_DNS: - case CMP_RESULT_CODE_NO_TCP_CONNECTION: { + case CMP_RESULT_CODE_PROVISIONING_NETWORK: { String url = getMobileProvisioningUrl(); if (TextUtils.isEmpty(url) == false) { if (DBG) log("CheckMp.onComplete: warm (no dns/tcp), url=" + url); @@ -3971,8 +3975,8 @@ private synchronized Integer isMobileOk(Params params) { MobileDataStateTracker mdst = (MobileDataStateTracker) mCs.mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI]; if (mdst.isProvisioningNetwork()) { - if (DBG) log("isMobileOk: isProvisioningNetwork is true, no TCP conn"); - result = CMP_RESULT_CODE_NO_TCP_CONNECTION; + if (DBG) log("isMobileOk: isProvisioningNetwork is true"); + result = CMP_RESULT_CODE_PROVISIONING_NETWORK; return result; } else { if (DBG) log("isMobileOk: isProvisioningNetwork is false, continue"); @@ -4055,25 +4059,37 @@ private synchronized Integer isMobileOk(Params params) { // is used which is useless in this case. urlConn.setRequestProperty("Connection", "close"); int responseCode = urlConn.getResponseCode(); + + // For debug display the headers + Map> headers = urlConn.getHeaderFields(); + log("isMobileOk: headers=" + headers); + + // Close the connection + urlConn.disconnect(); + urlConn = null; + if (responseCode == 204) { + // Return + log("isMobileOk: expected responseCode=" + responseCode); result = CMP_RESULT_CODE_CONNECTABLE; + return result; } else { + // Retry to be sure this was redirected, we've gotten + // occasions where a server returned 200 even though + // the device didn't have a "warm" sim. + log("isMobileOk: not expected responseCode=" + responseCode); result = CMP_RESULT_CODE_REDIRECTED; } - log("isMobileOk: connected responseCode=" + responseCode); - urlConn.disconnect(); - urlConn = null; - return result; } catch (Exception e) { log("isMobileOk: HttpURLConnection Exception e=" + e); + result = CMP_RESULT_CODE_NO_TCP_CONNECTION; if (urlConn != null) { urlConn.disconnect(); urlConn = null; } } } - result = CMP_RESULT_CODE_NO_TCP_CONNECTION; - log("isMobileOk: loops|timed out"); + log("isMobileOk: loops|timed out result=" + result); return result; } catch (Exception e) { log("isMobileOk: Exception e=" + e); From 002a0d579b007c9b6692e62d7c629c0cec029a0b Mon Sep 17 00:00:00 2001 From: Wink Saville Date: Fri, 13 Sep 2013 12:40:11 -0700 Subject: [PATCH 137/204] checkMobileProvisioning should not block. In checkMobileProvisioning the call to mdst.isProvisioningNetwork() is a blocking call and during monkey testing without SIM this is causing ANR's. Move the initial test for provisioning into isMobileOk so checkMobileProvisioning doesn't block. If mobile is not supported return CMP_RESULT_NO_CONNECTION. Cleaned up some debug. Bug: 10674404 Change-Id: I10a0e922cd6ea9790f66e2083f37e68cb0a8861f --- .../android/server/ConnectivityService.java | 63 +++++++------------ 1 file changed, 24 insertions(+), 39 deletions(-) diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index d844f9f4a6277..ddd480c10dcb2 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -3745,40 +3745,6 @@ public int checkMobileProvisioning(int suggestedTimeOutMs) { // Start off with notification off setProvNotificationVisible(false, ConnectivityManager.TYPE_NONE, null, null); - // See if we've alreadying determined if we've got a provsioning connection - // if so we don't need to do anything active - MobileDataStateTracker mdstDefault = (MobileDataStateTracker) - mNetTrackers[ConnectivityManager.TYPE_MOBILE]; - boolean isDefaultProvisioning = mdstDefault.isProvisioningNetwork(); - - MobileDataStateTracker mdstHipri = (MobileDataStateTracker) - mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI]; - boolean isHipriProvisioning = mdstHipri.isProvisioningNetwork(); - - if (isDefaultProvisioning || isHipriProvisioning) { - if (mIsNotificationVisible) { - if (DBG) { - log("checkMobileProvisioning: provisioning-ignore notification is visible"); - } - } else { - NetworkInfo ni = null; - if (isDefaultProvisioning) { - ni = mdstDefault.getNetworkInfo(); - } - if (isHipriProvisioning) { - ni = mdstHipri.getNetworkInfo(); - } - String url = getMobileProvisioningUrl(); - if ((ni != null) && (!TextUtils.isEmpty(url))) { - setProvNotificationVisible(true, ni.getType(), ni.getExtraInfo(), url); - } else { - if (DBG) log("checkMobileProvisioning: provisioning but no url, ignore"); - } - } - mIsCheckingMobileProvisioning.set(false); - return timeOutMs; - } - CheckMp checkMp = new CheckMp(mContext, this); CheckMp.CallBack cb = new CheckMp.CallBack() { @Override @@ -3912,8 +3878,26 @@ private synchronized Integer isMobileOk(Params params) { mParams = params; if (mCs.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false) { - log("isMobileOk: not mobile capable"); result = CMP_RESULT_CODE_NO_CONNECTION; + log("isMobileOk: X not mobile capable result=" + result); + return result; + } + + // See if we've already determined we've got a provisioning connection, + // if so we don't need to do anything active. + MobileDataStateTracker mdstDefault = (MobileDataStateTracker) + mCs.mNetTrackers[ConnectivityManager.TYPE_MOBILE]; + boolean isDefaultProvisioning = mdstDefault.isProvisioningNetwork(); + log("isMobileOk: isDefaultProvisioning=" + isDefaultProvisioning); + + MobileDataStateTracker mdstHipri = (MobileDataStateTracker) + mCs.mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI]; + boolean isHipriProvisioning = mdstHipri.isProvisioningNetwork(); + log("isMobileOk: isHipriProvisioning=" + isHipriProvisioning); + + if (isDefaultProvisioning || isHipriProvisioning) { + result = CMP_RESULT_CODE_PROVISIONING_NETWORK; + log("isMobileOk: X default || hipri is provisioning result=" + result); return result; } @@ -3975,8 +3959,8 @@ private synchronized Integer isMobileOk(Params params) { MobileDataStateTracker mdst = (MobileDataStateTracker) mCs.mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI]; if (mdst.isProvisioningNetwork()) { - if (DBG) log("isMobileOk: isProvisioningNetwork is true"); result = CMP_RESULT_CODE_PROVISIONING_NETWORK; + if (DBG) log("isMobileOk: X isProvisioningNetwork result=" + result); return result; } else { if (DBG) log("isMobileOk: isProvisioningNetwork is false, continue"); @@ -3991,8 +3975,8 @@ private synchronized Integer isMobileOk(Params params) { try { addresses = InetAddress.getAllByName(orgUri.getHost()); } catch (UnknownHostException e) { - log("isMobileOk: UnknownHostException"); result = CMP_RESULT_CODE_NO_DNS; + log("isMobileOk: X UnknownHostException result=" + result); return result; } log("isMobileOk: addresses=" + inetAddressesToString(addresses)); @@ -4070,8 +4054,9 @@ private synchronized Integer isMobileOk(Params params) { if (responseCode == 204) { // Return - log("isMobileOk: expected responseCode=" + responseCode); result = CMP_RESULT_CODE_CONNECTABLE; + log("isMobileOk: X expected responseCode=" + responseCode + + " result=" + result); return result; } else { // Retry to be sure this was redirected, we've gotten @@ -4089,7 +4074,7 @@ private synchronized Integer isMobileOk(Params params) { } } } - log("isMobileOk: loops|timed out result=" + result); + log("isMobileOk: X loops|timed out result=" + result); return result; } catch (Exception e) { log("isMobileOk: Exception e=" + e); From ebdf3a2f32e6fb8b388505131ab59f0b64b5dbab Mon Sep 17 00:00:00 2001 From: Wink Saville Date: Thu, 3 Oct 2013 08:34:46 -0700 Subject: [PATCH 138/204] Use networkType to display wifi and mobile notification separately. There are two bugs one is I was clearing the notification in CaptivePortalTracker when entering the ActivateState. (double check according to bug 5021626 we should be calling enter) Second is we could have the need to display both icons but can't because we only allow one. The solution I'm proposing here is to allow two notifications and have then controlled separately. Bug: 10886908 Change-Id: I30e7130bc542535492d175640a4990c592f32806 --- core/java/android/net/CaptivePortalTracker.java | 16 ++++++---------- .../com/android/server/ConnectivityService.java | 16 +++++++++------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/core/java/android/net/CaptivePortalTracker.java b/core/java/android/net/CaptivePortalTracker.java index 19c5f39eae4c8..0f7d9a088b2c4 100644 --- a/core/java/android/net/CaptivePortalTracker.java +++ b/core/java/android/net/CaptivePortalTracker.java @@ -157,10 +157,6 @@ public void detectCaptivePortal(NetworkInfo info) { } private class DefaultState extends State { - @Override - public void enter() { - setNotificationOff(); - } @Override public boolean processMessage(Message message) { @@ -186,6 +182,7 @@ public boolean processMessage(Message message) { private class NoActiveNetworkState extends State { @Override public void enter() { + setNotificationOff(); mNetworkInfo = null; } @@ -214,11 +211,6 @@ public boolean processMessage(Message message) { } private class ActiveNetworkState extends State { - @Override - public void enter() { - setNotificationOff(); - } - @Override public boolean processMessage(Message message) { NetworkInfo info; @@ -262,6 +254,8 @@ public boolean processMessage(Message message) { if (DBG) log(getName() + message.toString()); switch (message.what) { case CMD_DELAYED_CAPTIVE_CHECK: + setNotificationOff(); + if (message.arg1 == mDelayedCheckToken) { InetAddress server = lookupHost(mServer); boolean captive = server != null && isCaptivePortal(server); @@ -340,8 +334,10 @@ private boolean isActiveNetwork(NetworkInfo info) { private void setNotificationOff() { try { - mConnService.setProvisioningNotificationVisible(false, ConnectivityManager.TYPE_NONE, + if (mNetworkInfo != null) { + mConnService.setProvisioningNotificationVisible(false, mNetworkInfo.getType(), null, null); + } } catch (RemoteException e) { log("setNotificationOff: " + e); } diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index ddd480c10dcb2..8b2e5adce8f8b 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -3742,8 +3742,8 @@ public int checkMobileProvisioning(int suggestedTimeOutMs) { return timeOutMs; } - // Start off with notification off - setProvNotificationVisible(false, ConnectivityManager.TYPE_NONE, null, null); + // Start off with mobile notification off + setProvNotificationVisible(false, ConnectivityManager.TYPE_MOBILE_HIPRI, null, null); CheckMp checkMp = new CheckMp(mContext, this); CheckMp.CallBack cb = new CheckMp.CallBack() { @@ -3768,7 +3768,8 @@ void onComplete(Integer result) { } if (TextUtils.isEmpty(url) == false) { if (DBG) log("CheckMp.onComplete: warm (redirected), url=" + url); - setProvNotificationVisible(true, ni.getType(), ni.getExtraInfo(), + setProvNotificationVisible(true, + ConnectivityManager.TYPE_MOBILE_HIPRI, ni.getExtraInfo(), url); } else { if (DBG) log("CheckMp.onComplete: warm (redirected), no url"); @@ -3779,7 +3780,8 @@ void onComplete(Integer result) { String url = getMobileProvisioningUrl(); if (TextUtils.isEmpty(url) == false) { if (DBG) log("CheckMp.onComplete: warm (no dns/tcp), url=" + url); - setProvNotificationVisible(true, ni.getType(), ni.getExtraInfo(), + setProvNotificationVisible(true, + ConnectivityManager.TYPE_MOBILE_HIPRI, ni.getExtraInfo(), url); } else { if (DBG) log("CheckMp.onComplete: warm (no dns/tcp), no url"); @@ -4198,7 +4200,7 @@ public void onReceive(Context context, Intent intent) { private void handleMobileProvisioningAction(String url) { // Notication mark notification as not visible - setProvNotificationVisible(false, ConnectivityManager.TYPE_NONE, null, null); + setProvNotificationVisible(false, ConnectivityManager.TYPE_MOBILE_HIPRI, null, null); // If provisioning network handle as a special case, // otherwise launch browser with the intent directly. @@ -4284,14 +4286,14 @@ private void setProvNotificationVisible(boolean visible, int networkType, String notification.setLatestEventInfo(mContext, title, details, notification.contentIntent); try { - notificationManager.notify(NOTIFICATION_ID, 1, notification); + notificationManager.notify(NOTIFICATION_ID, networkType, notification); } catch (NullPointerException npe) { loge("setNotificaitionVisible: visible notificationManager npe=" + npe); npe.printStackTrace(); } } else { try { - notificationManager.cancel(NOTIFICATION_ID, 1); + notificationManager.cancel(NOTIFICATION_ID, networkType); } catch (NullPointerException npe) { loge("setNotificaitionVisible: cancel notificationManager npe=" + npe); npe.printStackTrace(); From 45fbca4507cf6a8870dc26cf1ce0fc6f14265025 Mon Sep 17 00:00:00 2001 From: Shashank Mittal Date: Fri, 16 Aug 2013 01:09:28 -0700 Subject: [PATCH 139/204] AppOpsService: Add MODE_ASK support to AppOps. Add support for new mode(MODE_ASK) in AppOpsService to show a permission dialog box to user to confirm user permission before allowing or ignoring that operation. All strict operations (defined in AppOpsManager) are going to be in MODE_ASK by default. Operations will be moved to MODE_ALLOWED or MODE_IGNORED according to user's choice. Change-Id: I1314125a2b8be558e422e4a9eea0ff066c21bf94 --- core/java/android/app/AppOpsManager.java | 51 ++++ .../layout/permission_confirmation_dialog.xml | 46 +++ core/res/res/values/cm_arrays.xml | 34 +++ core/res/res/values/symbols.xml | 12 +- .../com/android/server/AppOpsService.java | 271 +++++++++++++++--- .../android/server/BasePermissionDialog.java | 84 ++++++ .../com/android/server/PermissionDialog.java | 134 +++++++++ .../server/PermissionDialogResult.java | 109 +++++++ 8 files changed, 695 insertions(+), 46 deletions(-) create mode 100644 core/res/res/layout/permission_confirmation_dialog.xml create mode 100644 services/java/com/android/server/BasePermissionDialog.java create mode 100644 services/java/com/android/server/PermissionDialog.java create mode 100644 services/java/com/android/server/PermissionDialogResult.java diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index d7be2b811977a..508ab84e1a5bb 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -1,4 +1,7 @@ /* + * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -59,6 +62,7 @@ public class AppOpsManager { public static final int MODE_ALLOWED = 0; public static final int MODE_IGNORED = 1; public static final int MODE_ERRORED = 2; + public static final int MODE_ASK = 3; // when adding one of these: // - increment _NUM_OP @@ -99,6 +103,46 @@ public class AppOpsManager { /** @hide */ public static final int _NUM_OP = 31; + /** + * Map to check if each operation is strict or not, to determine default + * value of each operation. + * If strict then AppOpsService should assign MODE_ASK value to operation + * by default. + */ + private static boolean[] sOpStrict = new boolean[] { + true, //OP_COARSE_LOCATION + true, //OP_FINE_LOCATION + true, //OP_GPS + false, //OP_VIBRATE + true, //OP_READ_CONTACTS + true, //OP_WRITE_CONTACTS + true, //OP_READ_CALL_LOG + true, //OP_WRITE_CALL_LOG + false, //OP_READ_CALENDAR + false, //OP_WRITE_CALENDAR + true, //OP_WIFI_SCAN + false, //OP_POST_NOTIFICATION + false, //OP_NEIGHBORING_CELLS + true, //OP_CALL_PHONE + true, //OP_READ_SMS + true, //OP_WRITE_SMS + true, //OP_RECEIVE_SMS + false, //OP_RECEIVE_EMERGECY_SMS + true, //OP_RECEIVE_MMS + false, //OP_RECEIVE_WAP_PUSH + true, //OP_SEND_SMS + true, //OP_READ_ICC_SMS + true, //OP_WRITE_ICC_SMS + false, //OP_WRITE_SETTINGS + false, //OP_SYSTEM_ALERT_WINDOW + false, //OP_ACCESS_NOTIFICATIONS + true, //OP_CAMERA + true, //OP_RECORD_AUDIO + true, //OP_PLAY_AUDIO + false, //OP_READ_CLIPBOARD + false, //OP_WRITE_CLIPBOARD + }; + /** * This maps each operation to the operation that serves as the * switch to determine whether it is allowed. Generally this is @@ -217,6 +261,13 @@ public class AppOpsManager { null, // no permission for writing clipboard }; + /** + * Check if given operation is strict or not. + */ + public static boolean opStrict(int op) { + return sOpStrict[op]; + } + /** * Retrieve the op switch that controls the given operation. */ diff --git a/core/res/res/layout/permission_confirmation_dialog.xml b/core/res/res/layout/permission_confirmation_dialog.xml new file mode 100644 index 0000000000000..8a936e86bcf12 --- /dev/null +++ b/core/res/res/layout/permission_confirmation_dialog.xml @@ -0,0 +1,46 @@ + + + + + + + + + + diff --git a/core/res/res/values/cm_arrays.xml b/core/res/res/values/cm_arrays.xml index 6fac86768ec63..b62dbf27d80a3 100644 --- a/core/res/res/values/cm_arrays.xml +++ b/core/res/res/values/cm_arrays.xml @@ -52,4 +52,38 @@ 2 + + + Trying to access location + Trying to access location + Trying to access location + Trying to use vibrate + Trying to read contacts + Trying to modify contacts + Trying to read call log + Trying to modify call log + Trying to read calendar + Trying to modify calendar + Trying to access location + Trying to post notification + Trying to access location + Trying to make phone call + Trying to read SMS/MMS + Trying to write/modify SMS/MMS + Trying to receive SMS/MMS + Trying to receive SMS/MMS + Trying to receive SMS/MMS + Trying to receive SMS/MMS + Trying to send SMS/MMS + Trying to read SMS/MMS + Trying to write/modify SMS/MMS + Trying to modify settings + Trying to draw on top + Trying to access notifications + Trying to access Camera + Trying to record audio + Trying to play audio + Trying to read clipboard + Trying to modify clipboard + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 6eed4fa925dc4..12f1e74ca01be 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1,6 +1,9 @@ + Fehlgeschlagen. Aktivieren Sie die SIM-Kartensperre. + Falscher PUK-Code + Entsperren mit PIN fehlgeschlagen + Entsperren mit PUK fehlgeschlagen + Code akzeptiert + \nVerbleibende Versuche: + Ungültige Karte + SIM-Karte ist ungültig + SIM-Karte ist gesperrt + USSD-Anfrage wurde in DIAL-Anfrage umgewandelt + USSD-Anfrage wurde in SS-Anfrage umgewandelt + USSD-Anfrage wurde in neue USSD-Anfrage umgewandelt + SS-Anfrage wurde in DIAL-Anfrage umgewandelt + SS-Anfrage wurde in USSD-Anfrage umgewandelt + SS-Anfrage wurde in neue SS-Anfrage umgewandelt + Vertrag:%d : %s. + %s, %s From 206803396417e7a3383a681ce383ac57710c41d4 Mon Sep 17 00:00:00 2001 From: Shashank Mittal Date: Thu, 3 Jan 2013 20:05:33 -0800 Subject: [PATCH 147/204] services: Add hook to run device specific shutdown code. Add hook to call OEM specific shutdown synchronously. OEMs need to add ShutdownOem class and define deviceRebootOrShutdown function in that. ShutdownThread class would call this OEM defined function just before shutting down the device. Change-Id: I620495bfc99c6b0855a98ac54c6ede96e20ff1b8 --- .../android/server/power/ShutdownThread.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/services/java/com/android/server/power/ShutdownThread.java b/services/java/com/android/server/power/ShutdownThread.java index 9760d72f94518..fda353efdfa84 100644 --- a/services/java/com/android/server/power/ShutdownThread.java +++ b/services/java/com/android/server/power/ShutdownThread.java @@ -55,6 +55,7 @@ import android.util.Log; import android.view.WindowManager; import android.view.KeyEvent; +import java.lang.reflect.Method; public final class ShutdownThread extends Thread { // constants @@ -626,8 +627,35 @@ public static void rebootOrShutdown(boolean reboot, String reason) { } } + // Oem specific shutdown + deviceRebootOrShutdown(reboot, reason); + // Shutdown power Log.i(TAG, "Performing low-level shutdown..."); PowerManagerService.lowLevelShutdown(); } + + private static void deviceRebootOrShutdown(boolean reboot, String reason) { + + Class cl; + String deviceShutdownClassName = "com.android.server.power.ShutdownOem"; + + try{ + cl = Class.forName(deviceShutdownClassName); + Method m; + try { + m = cl.getMethod("rebootOrShutdown", new Class[]{boolean.class, String.class}); + m.invoke(cl.newInstance(), reboot, reason); + + } catch (NoSuchMethodException ex) { + //Method not found. + } catch (Exception ex) { + //Unknown exception + } + }catch(ClassNotFoundException e){ + //Classnotfound! + }catch(Exception e){ + //Unknown exception + } + } } From 42ded4a51e30a1f02e2578c5c28da8a06533f844 Mon Sep 17 00:00:00 2001 From: David Ng Date: Tue, 7 May 2013 11:56:06 -0700 Subject: [PATCH 148/204] services: Fix device-specific shutdown hook to support restart Update device-specific shutdown hook such that it is invoked for restart as well as for shutdown. Change-Id: I8c9cbe674000e0d664d41ecc98a341112e1cb060 --- services/java/com/android/server/power/ShutdownThread.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/java/com/android/server/power/ShutdownThread.java b/services/java/com/android/server/power/ShutdownThread.java index fda353efdfa84..66d0978c36b99 100644 --- a/services/java/com/android/server/power/ShutdownThread.java +++ b/services/java/com/android/server/power/ShutdownThread.java @@ -603,6 +603,9 @@ public void run() { * @param reason reason for reboot */ public static void rebootOrShutdown(boolean reboot, String reason) { + // Oem specific shutdown + deviceRebootOrShutdown(reboot, reason); + if (reboot) { Log.i(TAG, "Rebooting, reason: " + reason); try { @@ -627,9 +630,6 @@ public static void rebootOrShutdown(boolean reboot, String reason) { } } - // Oem specific shutdown - deviceRebootOrShutdown(reboot, reason); - // Shutdown power Log.i(TAG, "Performing low-level shutdown..."); PowerManagerService.lowLevelShutdown(); From b437a7457b06a1c0e52cf9c6fe6d20bd330a95c4 Mon Sep 17 00:00:00 2001 From: Abhishek Arpure Date: Wed, 18 Sep 2013 18:34:43 +0530 Subject: [PATCH 149/204] EMFILE exception in system_server due to socket fd leaks NativeCrashListener creates a socket connection with debuggerd. When native crash is observed, NativeCrashListener gets new socket file descriptor from debuggered. This socket is never closed. Multiple native crashes are causing "Too many files opened" EMFILE exception in system_server. CRs-Fixed: 545566 Change-Id: Idb12e87a4f91c978169435ce95abe11b40c6d0dc --- .../java/com/android/server/am/NativeCrashListener.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/services/java/com/android/server/am/NativeCrashListener.java b/services/java/com/android/server/am/NativeCrashListener.java index a9454bd4a4bef..b4590963dc136 100644 --- a/services/java/com/android/server/am/NativeCrashListener.java +++ b/services/java/com/android/server/am/NativeCrashListener.java @@ -152,6 +152,14 @@ public void run() { Slog.d(TAG, "Exception writing ack: " + e.getMessage()); } } + finally { + try { + Slog.d(TAG, "Closing socket connection: " + peerFd); + Libcore.os.close(peerFd); + } catch (ErrnoException e) { + Slog.w(TAG, "Error closing socket connection", e); + } + } } } } From 7ed457080992b745b8a20da6eb5a4e73b88938ec Mon Sep 17 00:00:00 2001 From: Harry Yang Date: Tue, 29 Oct 2013 22:48:30 -0700 Subject: [PATCH 150/204] frameworks/base: Fix race conditions on resume/suspend using power key The wakelock PowerManagerService.Display sometimes cannot be released after two quick power key pressings like a double click during phone sleep (the target will resume then supposedly suspend shortly). The second key event disturbs display power state on resume, as a result display resources won't get released on suspend, which is fixed in this change. CRs-Fixed: 566059 Change-Id: I633fd377ab235f203ebfb649a74449a2385740c4 --- .../java/com/android/server/power/DisplayPowerController.java | 1 + 1 file changed, 1 insertion(+) diff --git a/services/java/com/android/server/power/DisplayPowerController.java b/services/java/com/android/server/power/DisplayPowerController.java index ec6f52a371429..ee5a5084d62b7 100644 --- a/services/java/com/android/server/power/DisplayPowerController.java +++ b/services/java/com/android/server/power/DisplayPowerController.java @@ -803,6 +803,7 @@ private void updatePowerState() { if (!mElectronBeamOffAnimator.isStarted()) { if (mPowerState.getElectronBeamLevel() == 0.0f) { setScreenOn(false); + unblockScreenOn(); } else if (mPowerState.prepareElectronBeam( mElectronBeamFadesConfig ? ElectronBeam.MODE_FADE : From 923105855ae9795f5b2bbfcc266a7a9e5d5187fe Mon Sep 17 00:00:00 2001 From: nagarw Date: Fri, 11 Oct 2013 15:37:22 +0530 Subject: [PATCH 151/204] /platform/frameworks/base: Fix SystemUI crash on Recent App Issue: SystemUI crash is observed when Context MenuItem is selected on the recent apps activity [Long pressing two recent apps at same time or Long press, lock and unlock the screen] Fix: Changed the code to make sure that only one context menu is active at a time and also dismissed the context menu on pause of the RecentsActivity CRs-Fixed: 539509 Change-Id: Ia50bed7bfad6fde7beeaec37fa6402177eee1d40 --- .../src/com/android/systemui/recent/RecentsActivity.java | 3 +++ .../src/com/android/systemui/recent/RecentsPanelView.java | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java index 62030ad194fd1..5ee291b8966eb 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java @@ -92,6 +92,9 @@ public void onPause() { R.anim.recents_return_to_launcher_enter, R.anim.recents_return_to_launcher_exit); mForeground = false; + if (mRecentsPanel != null) { + mRecentsPanel.dismissContextMenuIfAny(); + } super.onPause(); } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index d212787e829a5..5630b6bf7e69b 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -300,6 +300,11 @@ public boolean isInContentArea(int x, int y) { } } + public void dismissContextMenuIfAny() { + if(mPopup != null) { + mPopup.dismiss(); + } + } public void show(boolean show) { show(show, null, false, false); } @@ -787,6 +792,9 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { public void handleLongPress( final View selectedView, final View anchorView, final View thumbnailView) { + if(mPopup != null) { + mPopup.dismiss(); + } thumbnailView.setSelected(true); final PopupMenu popup = new PopupMenu(mContext, anchorView == null ? selectedView : anchorView); From 543565f14b6ffa11ba5749a441dc3c526142f52c Mon Sep 17 00:00:00 2001 From: Sam Mortimer Date: Sun, 10 Nov 2013 09:14:28 -0800 Subject: [PATCH 152/204] AppOps: Fix resetAllModes() in AppOpsService *) Array iteration with inline deletion was broken causing PrivacyGuard reset not to work properly. *) Kanged fixed code from Kitkat Change-Id: If36d38f9199e6282fe52eabc32cd652d8aca86fe --- .../java/com/android/server/AppOpsService.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/services/java/com/android/server/AppOpsService.java b/services/java/com/android/server/AppOpsService.java index 70b7ca64584b7..d21e4dc19d642 100644 --- a/services/java/com/android/server/AppOpsService.java +++ b/services/java/com/android/server/AppOpsService.java @@ -440,12 +440,14 @@ public void resetAllModes() { HashMap>> callbacks = null; synchronized (this) { boolean changed = false; - for (int i=0; i=0; i--) { HashMap packages = mUidOps.valueAt(i); - for (Map.Entry ent : packages.entrySet()) { + Iterator> it = packages.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry ent = it.next(); String packageName = ent.getKey(); Ops pkgOps = ent.getValue(); - for (int j=0; j=0; j--) { Op curOp = pkgOps.valueAt(j); if (curOp.mode != curOp.defaultMode) { curOp.mode = curOp.defaultMode; @@ -454,9 +456,17 @@ public void resetAllModes() { mOpModeWatchers.get(curOp.op)); callbacks = addCallbacks(callbacks, packageName, curOp.op, mPackageModeWatchers.get(packageName)); - pruneOp(curOp, mUidOps.keyAt(i), packageName); + if (curOp.time == 0 && curOp.rejectTime == 0) { + pkgOps.removeAt(j); + } } } + if (pkgOps.size() == 0) { + it.remove(); + } + } + if (packages.size() == 0) { + mUidOps.removeAt(i); } } if (changed) { From 2a099881145b94402667e1a5364937383c7b77f0 Mon Sep 17 00:00:00 2001 From: Sam Mortimer Date: Fri, 27 Sep 2013 21:30:34 -0700 Subject: [PATCH 153/204] [2/2] AppOps: Add alarm wakeup op When alarm wakeups are denied/ignored, the alarm types are remapped as follows: RTC_WAKEUP -> RTC ELAPSED_REALTIME_WAKEUP -> ELAPSED_REALTIME Change-Id: I3a5023e1f6260004319290e776bdb2daf73e9fdf --- core/java/android/app/AppOpsManager.java | 7 ++- core/res/res/values/cm_arrays.xml | 1 + .../android/server/AlarmManagerService.java | 58 ++++++++++++++++++- 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index c23762c8d5365..cc2a7e477542a 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -104,7 +104,8 @@ public class AppOpsManager { public static final int OP_WIFI_CHANGE = 31; public static final int OP_BLUETOOTH_CHANGE = 32; public static final int OP_DATA_CONNECT_CHANGE = 33; - public static final int _NUM_OP = 34; + public static final int OP_ALARM_WAKEUP = 34; + public static final int _NUM_OP = 35; /** * Map to check if each operation is strict or not, to determine default @@ -147,6 +148,7 @@ public class AppOpsManager { true, //OP_WIFI_CHANGE true, //OP_BLUETOOTH_CHANGE true, //OP_DATA_CONNECT_CHANGE + false, //OP_ALARM_WAKEUP }; /** @@ -192,6 +194,7 @@ public class AppOpsManager { OP_WIFI_CHANGE, OP_BLUETOOTH_CHANGE, OP_DATA_CONNECT_CHANGE, + OP_ALARM_WAKEUP, }; /** @@ -233,6 +236,7 @@ public class AppOpsManager { "WIFI_CHANGE", "BLUETOOTH_CHANGE", "DATA_CONNECT_CHANGE", + "ALARM_WAKEUP", }; /** @@ -274,6 +278,7 @@ public class AppOpsManager { android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.BLUETOOTH, android.Manifest.permission.CHANGE_NETWORK_STATE, + null, // no permission for alarm wakeups }; /** diff --git a/core/res/res/values/cm_arrays.xml b/core/res/res/values/cm_arrays.xml index ba087ddf25322..6ab3088ddaa02 100644 --- a/core/res/res/values/cm_arrays.xml +++ b/core/res/res/values/cm_arrays.xml @@ -88,5 +88,6 @@ Trying to turn on/off Wifi Trying to turn on/off bluetooth Trying to turn on/off mobile data + Trying to schedule device wakeup diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java index fa758a88f4125..b810c65a338f6 100644 --- a/services/java/com/android/server/AlarmManagerService.java +++ b/services/java/com/android/server/AlarmManagerService.java @@ -19,6 +19,7 @@ import android.app.Activity; import android.app.ActivityManagerNative; import android.app.AlarmManager; +import android.app.AppOpsManager; import android.app.IAlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; @@ -106,6 +107,8 @@ class AlarmManagerService extends IAlarmManager.Stub { private final PendingIntent mTimeTickSender; private final PendingIntent mDateChangeSender; + private final AppOpsManager mAppOps; + private static final class InFlight extends Intent { final PendingIntent mPendingIntent; final Pair mTarget; @@ -197,6 +200,8 @@ public AlarmManagerService(Context context) { } else { Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler."); } + + mAppOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE); } protected void finalize() throws Throwable { @@ -217,6 +222,24 @@ public void setRepeating(int type, long triggerAtTime, long interval, Slog.w(TAG, "set/setRepeating ignored because there is no intent"); return; } + + boolean wakeupFiltered = false; + if ((type == AlarmManager.RTC_WAKEUP + || type == AlarmManager.ELAPSED_REALTIME_WAKEUP) + && mAppOps.checkOpNoThrow(AppOpsManager.OP_ALARM_WAKEUP, + operation.getCreatorUid(), + operation.getCreatorPackage()) + != AppOpsManager.MODE_ALLOWED) { + + if (type == AlarmManager.RTC_WAKEUP) { + type = AlarmManager.RTC; + } else { + type = AlarmManager.ELAPSED_REALTIME; + } + + wakeupFiltered = true; + } + synchronized (mLock) { Alarm alarm = new Alarm(); alarm.type = type; @@ -225,7 +248,16 @@ public void setRepeating(int type, long triggerAtTime, long interval, alarm.operation = operation; // Remove this alarm if already scheduled. - removeLocked(operation); + removeNoWakeupLocked(operation); + final boolean foundExistingWakeup = removeWakeupLocked(operation); + + // note AppOp for accounting purposes + // skip if the alarm already existed + if (!foundExistingWakeup && wakeupFiltered) { + mAppOps.noteOpNoThrow(AppOpsManager.OP_ALARM_WAKEUP, + operation.getCreatorUid(), + operation.getCreatorPackage()); + } if (localLOGV) Slog.v(TAG, "set: " + alarm); @@ -344,21 +376,37 @@ public void removeLocked(PendingIntent operation) { removeLocked(mElapsedRealtimeAlarms, operation); } - private void removeLocked(ArrayList alarmList, + private boolean removeWakeupLocked(PendingIntent operation) { + final boolean rtcwake = removeLocked(mRtcWakeupAlarms, operation); + final boolean realtimewake = removeLocked(mElapsedRealtimeWakeupAlarms, operation); + + return rtcwake || realtimewake; + } + + private void removeNoWakeupLocked(PendingIntent operation) { + removeLocked(mRtcAlarms, operation); + removeLocked(mElapsedRealtimeAlarms, operation); + } + + private boolean removeLocked(ArrayList alarmList, PendingIntent operation) { if (alarmList.size() <= 0) { - return; + return false; } // iterator over the list removing any it where the intent match Iterator it = alarmList.iterator(); + boolean found = false; while (it.hasNext()) { Alarm alarm = it.next(); if (alarm.operation.equals(operation)) { + found = true; it.remove(); } } + + return found; } public void removeLocked(String packageName) { @@ -862,6 +910,10 @@ public void run() fs.numWakeup++; ActivityManagerNative.noteWakeupAlarm( alarm.operation); + // AppOps accounting + mAppOps.noteOpNoThrow(AppOpsManager.OP_ALARM_WAKEUP, + alarm.operation.getCreatorUid(), + alarm.operation.getCreatorPackage()); } } catch (PendingIntent.CanceledException e) { if (alarm.repeatInterval > 0) { From da6d8814fed261ea45007d66b7c247fc212fb6cb Mon Sep 17 00:00:00 2001 From: Sam Mortimer Date: Wed, 2 Oct 2013 22:06:42 -0700 Subject: [PATCH 154/204] [2/2] AppOps: Add per Op allowed and ignored counters Change-Id: Ifb3d25e17dbab082b816a0a655b4796a83af336b --- core/java/android/app/AppOpsManager.java | 26 +++++++++- .../android/internal/app/IAppOpsService.aidl | 1 + .../com/android/server/AppOpsService.java | 48 ++++++++++++++++++- 3 files changed, 72 insertions(+), 3 deletions(-) diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index cc2a7e477542a..76b129e5baf42 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -381,13 +381,18 @@ public static class OpEntry implements Parcelable { private final long mTime; private final long mRejectTime; private final int mDuration; + private final int mAllowedCount; + private final int mIgnoredCount; - public OpEntry(int op, int mode, long time, long rejectTime, int duration) { + public OpEntry(int op, int mode, long time, long rejectTime, int duration, + int allowedCount, int ignoredCount) { mOp = op; mMode = mode; mTime = time; mRejectTime = rejectTime; mDuration = duration; + mAllowedCount = allowedCount; + mIgnoredCount = ignoredCount; } public int getOp() { @@ -414,6 +419,14 @@ public int getDuration() { return mDuration == -1 ? (int)(System.currentTimeMillis()-mTime) : mDuration; } + public int getAllowedCount() { + return mAllowedCount; + } + + public int getIgnoredCount() { + return mIgnoredCount; + } + @Override public int describeContents() { return 0; @@ -426,6 +439,8 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeLong(mTime); dest.writeLong(mRejectTime); dest.writeInt(mDuration); + dest.writeInt(mAllowedCount); + dest.writeInt(mIgnoredCount); } OpEntry(Parcel source) { @@ -434,6 +449,8 @@ public void writeToParcel(Parcel dest, int flags) { mTime = source.readLong(); mRejectTime = source.readLong(); mDuration = source.readInt(); + mAllowedCount = source.readInt(); + mIgnoredCount = source.readInt(); } public static final Creator CREATOR = new Creator() { @@ -626,4 +643,11 @@ public void setPrivacyGuardSettingForPackage(int uid, String packageName, } catch (RemoteException e) { } } + + public void resetCounters() { + try { + mService.resetCounters(); + } catch (RemoteException e) { + } + } } diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl index fa73f8f2dd51e..8ff5c354aa6dd 100644 --- a/core/java/com/android/internal/app/IAppOpsService.aidl +++ b/core/java/com/android/internal/app/IAppOpsService.aidl @@ -34,6 +34,7 @@ interface IAppOpsService { List getOpsForPackage(int uid, String packageName, in int[] ops); void setMode(int code, int uid, String packageName, int mode); void resetAllModes(); + void resetCounters(); // Privacy guard methods boolean getPrivacyGuardSettingForPackage(int uid, String packageName); diff --git a/services/java/com/android/server/AppOpsService.java b/services/java/com/android/server/AppOpsService.java index d21e4dc19d642..f7cee38e61331 100644 --- a/services/java/com/android/server/AppOpsService.java +++ b/services/java/com/android/server/AppOpsService.java @@ -133,6 +133,8 @@ public final static class Op { public int nesting; public int tempNesting; public PermissionDialogResult dialogResult; + public int allowedCount; + public int ignoredCount; public Op(int _op, boolean strict) { op = _op; @@ -285,7 +287,8 @@ private ArrayList collectOps(Ops pkgOps, int[] ops) { for (int j=0; j collectOps(Ops pkgOps, int[] ops) { resOps = new ArrayList(); } resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time, - curOp.rejectTime, curOp.duration)); + curOp.rejectTime, curOp.duration, + curOp.allowedCount, curOp.ignoredCount)); } } } @@ -563,11 +567,13 @@ private void recordOperationLocked(int code, int uid, String packageName, int mo if (DEBUG) Log.d(TAG, "recordOperation: reject #" + mode + " for code " + switchCode + " (" + code + ") uid " + uid + " package " + packageName); op.rejectTime = System.currentTimeMillis(); + op.ignoredCount++; } else if (mode == AppOpsManager.MODE_ALLOWED) { if (DEBUG) Log.d(TAG, "recordOperation: allowing code " + code + " uid " + uid + " package " + packageName); op.time = System.currentTimeMillis(); op.rejectTime = 0; + op.allowedCount++; } } } @@ -1080,6 +1086,14 @@ void readUid(XmlPullParser parser, String pkgName) throws NumberFormatException, if (dur != null) { op.duration = Integer.parseInt(dur); } + String allowed = parser.getAttributeValue(null, "ac"); + if (allowed != null) { + op.allowedCount = Integer.parseInt(allowed); + } + String ignored = parser.getAttributeValue(null, "ic"); + if (ignored != null) { + op.ignoredCount = Integer.parseInt(ignored); + } HashMap pkgOps = mUidOps.get(uid); if (pkgOps == null) { pkgOps = new HashMap(); @@ -1149,6 +1163,14 @@ void writeState() { if (dur != 0) { out.attribute(null, "d", Integer.toString(dur)); } + int allowed = op.getAllowedCount(); + if (allowed != 0) { + out.attribute(null, "ac", Integer.toString(allowed)); + } + int ignored = op.getIgnoredCount(); + if (ignored != 0) { + out.attribute(null, "ic", Integer.toString(ignored)); + } out.endTag(null, "op"); } out.endTag(null, "uid"); @@ -1231,4 +1253,26 @@ public void setPrivacyGuardSettingForPackage(int uid, String packageName, boolea ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED); } } + + @Override + public void resetCounters() { + mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, + Binder.getCallingPid(), Binder.getCallingUid(), null); + synchronized (this) { + for (int i=0; i packages = mUidOps.valueAt(i); + for (Map.Entry ent : packages.entrySet()) { + String packageName = ent.getKey(); + Ops pkgOps = ent.getValue(); + for (int j=0; j Date: Sun, 20 Oct 2013 23:48:45 -0700 Subject: [PATCH 155/204] AppOps: track op persistence by name instead of id On XML write, include the op name. On XML read, map the name back to op id (if it exists). Persistent AppOp state now follows the op name instead numeric id. This means you can upgrade between versions of CM and the op number does not matter. Handy when merging with future android code drops (CM AppOp ids might be used by Google). Change-Id: Iffc02095b6838a34ff999f8db51c2c6739dd0db8 --- core/java/android/app/AppOpsManager.java | 12 ++++++++++++ services/java/com/android/server/AppOpsService.java | 12 +++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 76b129e5baf42..d5b3303e2c428 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -303,6 +303,18 @@ public static String opToName(int op) { return op < sOpNames.length ? sOpNames[op] : ("Unknown(" + op + ")"); } + /** + * Map a non-localized name for the operation back to the Op number + */ + public static int nameToOp(String name) { + for (int i = 0; i < sOpNames.length; i++) { + if (sOpNames[i].equals(name)) { + return i; + } + } + return OP_NONE; + } + /** * Retrieve the permission associated with an operation, or null if there is not one. */ diff --git a/services/java/com/android/server/AppOpsService.java b/services/java/com/android/server/AppOpsService.java index f7cee38e61331..284a5475016b5 100644 --- a/services/java/com/android/server/AppOpsService.java +++ b/services/java/com/android/server/AppOpsService.java @@ -1067,7 +1067,16 @@ void readUid(XmlPullParser parser, String pkgName) throws NumberFormatException, String tagName = parser.getName(); if (tagName.equals("op")) { - int code = Integer.parseInt(parser.getAttributeValue(null, "n")); + int code = AppOpsManager.OP_NONE; + String codeStr = parser.getAttributeValue(null, "n"); + if (codeStr != null) { + code = Integer.parseInt(codeStr); + } + /* use op name string if it exists */ + String codeNameStr = parser.getAttributeValue(null, "ns"); + if (codeNameStr != null) { + code = AppOpsManager.nameToOp(codeNameStr); + } boolean strict = isStrict(code, uid, pkgName); Op op = new Op(code, strict); String mode = parser.getAttributeValue(null, "m"); @@ -1150,6 +1159,7 @@ void writeState() { AppOpsManager.OpEntry op = ops.get(j); out.startTag(null, "op"); out.attribute(null, "n", Integer.toString(op.getOp())); + out.attribute(null, "ns", AppOpsManager.opToName(op.getOp())); out.attribute(null, "m", Integer.toString(op.getMode())); long time = op.getTime(); if (time != 0) { From 9e6266f6079483f81de17199277b289df65d266d Mon Sep 17 00:00:00 2001 From: isimobile Date: Mon, 4 Nov 2013 15:09:11 +0200 Subject: [PATCH 156/204] core:AF Translations Change-Id: I7205ba35a2b3079dd3fa3ebbba1d0507da588f35 --- core/res/res/values-af/cm_strings.xml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/core/res/res/values-af/cm_strings.xml b/core/res/res/values-af/cm_strings.xml index 33977a1d459eb..9a8d5e03de9d0 100644 --- a/core/res/res/values-af/cm_strings.xml +++ b/core/res/res/values-af/cm_strings.xml @@ -71,5 +71,24 @@ Wissel SELinux beleid: Dwing of permissiewe mode. Dwing MMAC Wissel MMAC beleid: Dwing of permissiewe mode. - + Onsuksesvol. Aktiveer SIM/RUIM grendel. + Verkeerde PUK kode! + PIN bywerking het misluk! + PUK bywerking het misluk! + Kode korek! + \nProbeerslae oor : + Ongeldige kaart. + SIM kaart is ongeldig. + SIM/RUIM is Perso-gesluit + USSD-versoek is verander na Skakel-versoek. + USSD-versoek is verander na SS-versoek. + USSD-versoek is verander na nuwe USSD versoek. + SS-versoek is verander na Skakel-versoek. + SS-versoek is verander na USSD-versoek. + SS-versoek is verander na nuwe SS-versoek. + SUB:%d : %s. + %s, %s + Bespaar krag + Gebalanseerd + Werkverrigting From 09447ecaf461b5bff6bdd5930bbbdba41899c9f6 Mon Sep 17 00:00:00 2001 From: Lorenzo M Date: Tue, 12 Nov 2013 23:40:10 +0100 Subject: [PATCH 157/204] core: ES translations - AppOps Change-Id: I2e500b237853d8fbda3d22639ba5980b348a78cf --- core/res/res/values-es/cm_arrays.xml | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 core/res/res/values-es/cm_arrays.xml diff --git a/core/res/res/values-es/cm_arrays.xml b/core/res/res/values-es/cm_arrays.xml new file mode 100644 index 0000000000000..c5a8c116bcb14 --- /dev/null +++ b/core/res/res/values-es/cm_arrays.xml @@ -0,0 +1,55 @@ + + + + + Intenta acceder a la ubicación + Intenta acceder a la ubicación + Intenta acceder a la ubicación + Intenta utilizar la vibración + Intenta consultar tus contactos + Intenta modificar tus contactos + Intenta leer el registro de llamadas + Intenta modificar el registro de llamadas + Intenta leer eventos de calendario + Intenta añadir o modificar eventos de calendario + Intenta acceder a la ubicación + Intenta publicar una notificación + Intenta acceder a la ubicación + Intenta llamar directamente a un número de teléfono + Intenta leer tus mensajes SMS/MMS + Intenta editar tus mensajes SMS/MMS + Intenta recibir mensajes SMS/MMS + Intenta recibir mensajes SMS/MMS + Intenta recibir mensajes SMS/MMS + Intenta recibir mensajes SMS/MMS + Intenta enviar mensajes SMS/MMS + Intenta leer tus mensajes SMS/MMS + Intenta editar tus mensajes SMS/MMS + Intenta modificar los ajustes del sistema + Intenta mostrarse sobre otras aplicaciones + Intenta acceder a las notificaciones + Intenta realizar fotografías y vídeo + Intenta grabar sonido + Intenta reproducir sonido + Intenta consultar el portapapeles + Intenta modificar el portapapeles + Intenta cambiar el estado de Wi-Fi + Intenta cambiar el estado de Bluetooth + Intenta cambiar el estado de la conexión de red + Intenta programar un encendido del dispositivo + + From 05856c2bc4c6d20dcdbf7d8f7ea8a32f909103e6 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Wed, 13 Nov 2013 03:57:08 -0800 Subject: [PATCH 158/204] camera: Better fix for face detection score issue * Do this at the lower layer so that third-party apps don't have issus with the nonstandard score. Change-Id: Ic012b092d2f47dbaab8cbfe2bd215b955800cc11 --- core/jni/Android.mk | 4 ++++ core/jni/android_hardware_Camera.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/core/jni/Android.mk b/core/jni/Android.mk index b07b3c8b9aa9e..53c92b35e6231 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -250,6 +250,10 @@ ifeq ($(WITH_MALLOC_LEAK_CHECK),true) LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK endif +ifeq ($(BOARD_FIX_FACE_DETECTION_SCORE),true) + LOCAL_CFLAGS += -DFIX_FACE_DETECTION_SCORE +endif + LOCAL_MODULE:= libandroid_runtime include $(BUILD_SHARED_LIBRARY) diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index de7666b675ab9..3525d13bcd5d2 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -384,7 +384,11 @@ void JNICameraContext::postMetadata(JNIEnv *env, int32_t msgType, camera_frame_m env->SetIntField(rect, fields.rect_right, metadata->faces[i].rect[2]); env->SetIntField(rect, fields.rect_bottom, metadata->faces[i].rect[3]); env->SetObjectField(face, fields.face_rect, rect); +#ifdef FIX_FACE_DETECTION_SCORE + env->SetIntField(face, fields.face_score, (metadata->faces[i].score ? 0 : 100)); +#else env->SetIntField(face, fields.face_score, metadata->faces[i].score); +#endif #ifdef QCOM_HARDWARE jobject point1 = env->NewObject(mPointClass, fields.point_constructor); From 1de8fb28be36b1ef43e00260ce0241ad0595108d Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Wed, 13 Nov 2013 23:43:59 -0800 Subject: [PATCH 159/204] Shell user needs UPDATE_APP_OPS_STATS * CTS fail with "bmgr run" Change-Id: Ic950cda4363f8f2a4edfcb330a4d5b506a6c3685 --- packages/Shell/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index ffb4c2026291c..63fdd094761b7 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -69,6 +69,7 @@ + Date: Thu, 26 Sep 2013 18:19:15 +0530 Subject: [PATCH 160/204] Avoid IndexOutOfBounds Exception in ActivityManager Bypass the iteration to avoid the exception during the execution of ensureActivityVisibleLocked() because startSpecificActivityLocked() within for loop may delete the elements from History stack. Change-Id: Iad9bdc6521b25b12d4c67e6b89f375a99b17748b CRs-Fixed: 535900 --- services/java/com/android/server/am/ActivityStack.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index c524a78e5f4cf..a158d070ce3ff 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -1308,6 +1308,10 @@ final void ensureActivitiesVisibleLocked(ActivityRecord top, ActivityRecord r; boolean behindFullscreen = false; for (; i>=0; i--) { + // To make sure index is valid as there might be the case when size of + // the history stack gets decremented within this for loop. + if (i >= mHistory.size()) + continue; r = mHistory.get(i); if (DEBUG_VISBILITY) Slog.v( TAG, "Make visible? " + r + " finishing=" + r.finishing From e9ba9cf94d42d76cbf1804f49ce1028d4825c429 Mon Sep 17 00:00:00 2001 From: Lingchao Xin Date: Thu, 14 Nov 2013 17:54:51 +0800 Subject: [PATCH 161/204] Frameworks/base: zh_CN translations Change-Id: I73d4d4b6c0b0879d940c35a67274766ad99c9e37 --- core/res/res/values-zh-rCN/cm_arrays.xml | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 core/res/res/values-zh-rCN/cm_arrays.xml diff --git a/core/res/res/values-zh-rCN/cm_arrays.xml b/core/res/res/values-zh-rCN/cm_arrays.xml new file mode 100644 index 0000000000000..f8ab955f2f3a7 --- /dev/null +++ b/core/res/res/values-zh-rCN/cm_arrays.xml @@ -0,0 +1,55 @@ + + + + + + 试图访问位置 + 试图访问位置 + 试图访问位置 + 试图使用震动 + 试图读取联系人 + 试图修改联系人 + 试图读取通话记录 + 试图修改通话记录 + 试图读取日历 + 试图修改日历 + 试图访问位置 + 试图传递通知 + 试图访问位置 + 试图打电话 + 试图读取 短信/彩信 + 试图 写/修改 短信/彩信 + 试图接收 短信/彩信 + 试图接收 短信/彩信 + 试图接收 短信/彩信 + 试图接收 短信/彩信 + 试图发送 短信/彩信 + 试图读取 短信/彩信 + 试图 写/修改 短信/彩信 + 试图修改设置 + 试图顶部绘制 + 试图访问通知 + 试图访问相机 + 试图录制音频 + 试图播放音频 + 试图读取剪贴板 + 试图修改剪贴板 + 试图 打开/关闭 Wifi + 试图 打开/关闭 蓝牙 + 试图 打开/关闭 移动数据 + 试图 延迟设备唤醒 + + From ba912eb1ffe7403a24abb3004f6dc5293aec0201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20J=C3=B8rgensen?= Date: Thu, 14 Nov 2013 21:07:12 +0100 Subject: [PATCH 162/204] frameworks_base: DA translation Patch Set 2: Added a missing < Change-Id: I6cc15e09963ad72127c3fe5eced1ec9d19f7e95b --- core/res/res/values-da/cm_arrays.xml | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 core/res/res/values-da/cm_arrays.xml diff --git a/core/res/res/values-da/cm_arrays.xml b/core/res/res/values-da/cm_arrays.xml new file mode 100644 index 0000000000000..accc87547fa1d --- /dev/null +++ b/core/res/res/values-da/cm_arrays.xml @@ -0,0 +1,55 @@ + + + + + + Forsøger at få adgang til placering + Forsøger at få adgang til placering + Forsøger at få adgang til placering + Forsøger at bruge vibration + Forsøger at læse kontaktpersoner + Forsøger at ændre kontaktpersoner + Forsøger at læse opkaldsloggen + Forsøger at ændre opkaldsloggen + Forsøger at læse kalenderen + Forsøger at ændre kalenderen + Forsøger at få adgang til placering + Forsøger at skrive notifikationen + Forsøger at få adgang til placering + Forsøger at lave et telefonopkald + Forsøger at læse SMS/MMS + Forsøger at skrive/ændre SMS/MMS + Forsøger at modtage SMS/MMS + Forsøger at modtage SMS/MMS + Forsøger at modtage SMS/MMS + Forsøger at modtage SMS/MMS + Forsøger at sende SMS/MMS + Forsøger at læse SMS/MMS + Forsøger at skrive/ændre SMS/MMS + Forsøger at ændre indstillinger + Forsøger at trække på toppen + Forsøger at få adgang til notifikationer + Forsøger at få adgang til Kamera + Forsøger at optage lyd + Forsøger at afspille lyd + Forsøger at læse udklipsholderen + Forsøger at ændre udklipsholderen + Forsøger at slå Wifi til/fra + Forsøger at slå bluetooth til/fra + Forsøger at slå mobildata til/fra + Forsøger at planlægge opvågning af enheden + + From 068b5f4279a1db3365a13881e5beeaa0a09dc90d Mon Sep 17 00:00:00 2001 From: Danesh M Date: Thu, 14 Nov 2013 19:44:02 -0800 Subject: [PATCH 163/204] AudioService : Ensure uri is not null Checks to make sure the uri is not null, otherwise the entire subsystem crashes. Change-Id: Iac04b6d11335236d527b8d5a1ccb48c1e09a4ac2 --- media/java/android/media/AudioService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index ab376c25553f8..84599c448be00 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -3742,6 +3742,9 @@ private class SettingsObserver extends ContentObserver { @Override public void onChange(boolean selfChange, Uri uri) { super.onChange(selfChange, uri); + if (uri == null) { + return; + } // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode. // However there appear to be some missing locks around mRingerModeMutedStreams // and mRingerModeAffectedStreams, so will leave this synchronized for now. From 927c044d762a794af89a32fef1386fb134afc231 Mon Sep 17 00:00:00 2001 From: Ethan Chen Date: Thu, 14 Nov 2013 20:15:04 -0800 Subject: [PATCH 164/204] Show owner info creation if no owner is set for UserTile Change-Id: I43575946023676a1b75b67e1ae1996a0a3a35b88 --- .../android/systemui/quicksettings/UserTile.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java b/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java index 1bcbe459f1b53..ece5a8766c153 100644 --- a/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java +++ b/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java @@ -14,6 +14,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.provider.ContactsContract; +import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.Profile; import android.util.Log; @@ -31,6 +32,7 @@ public class UserTile extends QuickSettingsTile { private static final String TAG = "UserTile"; + private static final String INTENT_EXTRA_NEW_LOCAL_PROFILE = "newLocalProfile"; private Drawable userAvatar; private AsyncTask> mUserInfoTask; @@ -43,16 +45,21 @@ public void onClick(View v) { mQsc.mBar.collapseAllPanels(true); final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - if (um.getUsers(true).size() > 1) { + int numUsers = um.getUsers(true).size(); + if (numUsers == 0) { + Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI); + intent.putExtra(INTENT_EXTRA_NEW_LOCAL_PROFILE, true); + startSettingsActivity(intent); + } else if (numUsers == 1) { + Intent intent = new Intent(Intent.ACTION_VIEW, ContactsContract.Profile.CONTENT_URI); + startSettingsActivity(intent); + } else { try { WindowManagerGlobal.getWindowManagerService().lockNow( null); } catch (RemoteException e) { Log.e(TAG, "Couldn't show user switcher", e); } - } else { - Intent intent = new Intent(Intent.ACTION_VIEW, ContactsContract.Profile.CONTENT_URI); - startSettingsActivity(intent); } } }; From 816e30d49c9cecee7ccbda3b6256ff2b1d61ad32 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Sat, 16 Nov 2013 03:35:12 -0800 Subject: [PATCH 165/204] Revert "/platform/frameworks/base: Fix SystemUI crash on Recent App" * Causing even worse behavior. This reverts commit 923105855ae9795f5b2bbfcc266a7a9e5d5187fe. Change-Id: Ie69107b9e1cf37c98d17900d1abb62ed9c0dfe43 --- .../src/com/android/systemui/recent/RecentsActivity.java | 3 --- .../src/com/android/systemui/recent/RecentsPanelView.java | 8 -------- 2 files changed, 11 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java index 5ee291b8966eb..62030ad194fd1 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java @@ -92,9 +92,6 @@ public void onPause() { R.anim.recents_return_to_launcher_enter, R.anim.recents_return_to_launcher_exit); mForeground = false; - if (mRecentsPanel != null) { - mRecentsPanel.dismissContextMenuIfAny(); - } super.onPause(); } diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java index 5630b6bf7e69b..d212787e829a5 100644 --- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java @@ -300,11 +300,6 @@ public boolean isInContentArea(int x, int y) { } } - public void dismissContextMenuIfAny() { - if(mPopup != null) { - mPopup.dismiss(); - } - } public void show(boolean show) { show(show, null, false, false); } @@ -792,9 +787,6 @@ public boolean onInterceptTouchEvent(MotionEvent ev) { public void handleLongPress( final View selectedView, final View anchorView, final View thumbnailView) { - if(mPopup != null) { - mPopup.dismiss(); - } thumbnailView.setSelected(true); final PopupMenu popup = new PopupMenu(mContext, anchorView == null ? selectedView : anchorView); From fc7b6ffd8f25dd98c9057fbb33653d736038dc20 Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Sun, 17 Nov 2013 00:17:19 +0200 Subject: [PATCH 166/204] core: EL translations Change-Id: I58c24250bb186d9b9d5b2bda88aa78941c1561f5 --- core/res/res/values-el/cm_arrays.xml | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 core/res/res/values-el/cm_arrays.xml diff --git a/core/res/res/values-el/cm_arrays.xml b/core/res/res/values-el/cm_arrays.xml new file mode 100644 index 0000000000000..cc9721988587a --- /dev/null +++ b/core/res/res/values-el/cm_arrays.xml @@ -0,0 +1,55 @@ + + + + + Προσπάθεια πρόσβασης τοποθεσίας + Προσπάθεια πρόσβασης τοποθεσίας + Προσπάθεια πρόσβασης τοποθεσίας + Προσπάθεια χρήσης δόνησης + Προσπάθεια ανάγνωσης επαφών + Προσπάθεια τροποποίησης επαφών + Προσπάθεια ανάγνωσης αρχείου κλήσεων + Προσπάθεια τροποποίησης αρχείου κλήσεων + Προσπάθεια ανάγνωσης ημερολογίου + Προσπάθεια τροποποίησης ημερολογίου + Προσπάθεια πρόσβασης τοποθεσίας + Προσπάθεια δημοσίευσης ειδοποίησης + Προσπάθεια πρόσβασης τοποθεσίας + Προσπάθεια τηλεφωνικής κλήσης + Προσπάθεια ανάγνωσης SMS/MMS + Προσπάθεια σύνταξης/τροποποίησης SMS/MMS + Προσπάθεια λήψης SMS/MMS + Προσπάθεια λήψης SMS/MMS + Προσπάθεια λήψης SMS/MMS + Προσπάθεια λήψης SMS/MMS + Προσπάθεια αποστολής SMS/MMS + Προσπάθεια ανάγνωσης SMS/MMS + Προσπάθεια εγγραφής/τροποποίησης SMS/MMS + Προσπάθεια τροποποίησης ρυθμίσεων + Προσπάθεια μεταφοράς στην κορυφή + Προσπάθεια πρόσβασης ειδοποιήσεων + Προσπάθεια πρόσβασης φωτογρ. μηχανής + Προσπάθεια ηχογράφησης + Προσπάθεια αναπαραγωγής ήχου + Προσπάθεια ανάγνωσης πρόχειρου + Προσπάθεια τροποποίησης πρόχειρου + Προσπάθεια ενεργοποίησης/απενεργοποίησης Wi-Fi + Προσπάθεια ενεργοποίησης/απενεργοποίησης Bluetooth + Προσπάθεια ενεργοποίησης/απενεργοποίησης δεδομένων + Προσπάθεια προγραμματισμού αφύπνισης συσκευής + + From 2f916d8fe26fb9f228eab3c2cab3dc45efba6b05 Mon Sep 17 00:00:00 2001 From: Francesco Date: Sun, 17 Nov 2013 11:57:25 +0100 Subject: [PATCH 167/204] frameworks/base: IT translations Change-Id: Ib5d2558b71f8f233368522059cad0f8a1f13bfe8 --- core/res/res/values-it/cm_arrays.xml | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 core/res/res/values-it/cm_arrays.xml diff --git a/core/res/res/values-it/cm_arrays.xml b/core/res/res/values-it/cm_arrays.xml new file mode 100644 index 0000000000000..6f3b53efd06fe --- /dev/null +++ b/core/res/res/values-it/cm_arrays.xml @@ -0,0 +1,55 @@ + + + + + Tentativo di accesso alla posizione + Tentativo di accesso alla posizione + Tentativo di accesso alla posizione + Tentativo di utilizzo della vibrazione + Tentativo di lettura dei contatti + Tentativo di modifica dei contatti + Tentativo di lettura del registro chiamate + Tentativo di modifica del registro chiamate + Tentativo di lettura calendario + Tentativo di modifica del calendario + Tentativo di accesso alla posizione + Tentativo di pubblicazione notifica + Tentativo di accesso alla posizione + Tentativo di chiamata + Tentativo di lettura SMS/MMS + Tentativo di scrittura/modifica SMS/MMS + Tentativo di ricezione SMS/MMS + Tentativo di ricezione SMS/MMS + Tentativo di ricezione SMS/MMS + Tentativo di ricezione SMS/MMS + Tentativo di invio SMS/MMS + Tentativo di lettura SMS/MMS + Tentativo di scrittura/modifica SMS/MMS + Tentativo di modifica delle impostazioni + Tentativo di tracciare in alto + Tentativo di accesso a notifiche + Tentativo di accesso alla fotocamera + Tentativo di registrazione audio + Tentativo di riproduzione audio + Tentativo di lettura degli appunti + Tentativo di modifica degli appunti + Tentativo di attivazione/disattivazione del Wi-Fi + Tentativo di attivazione/disattivazione del Bluetooth + Tentativo di attivazione/disattivazione dei dati mobili + Tentativo di programmazione risveglio del dispositivo + + From 1ba6b0651e174edbe64fff1058f5ff466c0fdd3c Mon Sep 17 00:00:00 2001 From: ywen Date: Tue, 24 Sep 2013 16:46:40 +0800 Subject: [PATCH 168/204] Fix stencil buffer bug. Stencil test is enabled by setStencilFromClip(), but not disabled in some use case, which causes some of the pixels are discarded by mistake in draws followed. Disable stencil test when there is no dirty clip. CRs-Fixed: 539456 Change-Id: I318fb47212e49e2da89bcbfd161a1689ef91b02f --- libs/hwui/OpenGLRenderer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 3f256ddd5e9fe..7e44748fc1a92 100755 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1659,6 +1659,12 @@ void OpenGLRenderer::setupDraw(bool clear) { setScissorFromClip(); } setStencilFromClip(); +#ifdef QCOM_BSP + } else { + // Disable stencil test in case setStencilFromClip() + // enabled the stencil test but didn't disable it + glDisable(GL_STENCIL_TEST); +#endif } mDescription.reset(); From 749fd726720331627e408b0f8a3e814e894f9ade Mon Sep 17 00:00:00 2001 From: William McVicker Date: Thu, 31 Oct 2013 10:42:32 -0700 Subject: [PATCH 169/204] Update the layer's alpha value upon composition of the layer Fixes: This patch makes sure that the layer's alpha value is up-to-date and does not reflect the previous view's alpha value. It fixes the square block on marquee fading edge when text view is applied transparency. CRs-Fixed: 562000 Change-Id: I397308b739f5f4fe4b630cf594825f401c97e0e3 --- libs/hwui/OpenGLRenderer.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 7e44748fc1a92..7c04453c5a64b 100755 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1015,7 +1015,17 @@ void OpenGLRenderer::composeLayer(sp current, sp previous) { } } else if (!rect.isEmpty()) { dirtyLayer(rect.left, rect.top, rect.right, rect.bottom); + +#ifdef QCOM_BSP + save(0); + // the layer contains screen buffer content that shouldn't be alpha modulated + // (and any necessary alpha modulation was handled drawing into the layer) + mSnapshot->alpha = 1.0f; +#endif composeLayerRect(layer, rect, true); +#ifdef QCOM_BSP + restore(); +#endif } dirtyClip(); From 75bb9191fcde66f7e51912878b9708e23cd593af Mon Sep 17 00:00:00 2001 From: Eddy Witkamp Date: Sat, 16 Nov 2013 17:07:19 +0100 Subject: [PATCH 170/204] framework: NL translation AppOpsService: Add MODE_ASK support to AppOps http://review.cyanogenmod.org/#/c/51063/9 Change-Id: I972703883aabfaadb145a2d67cd1ff055c398c12 --- core/res/res/values-nl/cm_arrays.xml | 56 ++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 core/res/res/values-nl/cm_arrays.xml diff --git a/core/res/res/values-nl/cm_arrays.xml b/core/res/res/values-nl/cm_arrays.xml new file mode 100644 index 0000000000000..04b2d1529f715 --- /dev/null +++ b/core/res/res/values-nl/cm_arrays.xml @@ -0,0 +1,56 @@ + + + + + + Probeert toegang te krijgen tot locatie + Probeert toegang te krijgen tot locatie + Probeert toegang te krijgen tot locatie + Probeert trillen te gebruiken + Probeert contacten te lezen + Probeert contacten aan te passen + Probeert oproeplogboek te lezen + Probeert oproeplogboek aan te passen + Probeert agenda te lezen + Probeert agenda aan te passen + Probeert toegang te krijgen tot locatie + Probeert melding te tonen + Probeert toegang te krijgen tot locatie + Probeert te bellen + Probeert sms/mms te lezen + Probeert sms/mms te schrijven/wijzigen + Probeert sms/mms te ontvangen + Probeert sms/mms te ontvangen + Probeert sms/mms te ontvangen + Probeert sms/mms te ontvangen + Probeert sms/mms te verzenden + Probeert sms/mms te lezen + Probeert sms/mms te schrijven/wijzigen + Probeert instellingen aan te passen + Probeert op de voorgrond te komen + Probeert toegang te krijgen tot meldingen + Probeert toegang te krijgen tot Camera + Probeert audio op te nemen + Probeert audio af te spelen + Probeert klembord te lezen + Probeert klembord aan te passen + Probeert wifi in/uit te schakelen + Probeert Bluetooth in/uit te schakelen + Probeert mobiele gegevens in/uit te schakelen + Probeert apparaat ontwaken in te plannen + + From 58c592330aafdb1afff07e41aaba1b02ca20a3b1 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Mon, 18 Nov 2013 17:21:19 -0800 Subject: [PATCH 171/204] telephony: Add support for additional emergency numbers * Some devices intended for international sale do not return proper emergency numbers in the ril.ecclist property. * Add support for a static list of emergency numbers to be appended to the list supplied by the radio. * Set "ro.ril.ext.ecclist" to use this. Change-Id: Ibe9cd26bf0b6a31453394efd55fea622b8832c11 --- telephony/java/android/telephony/PhoneNumberUtils.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index 063311918a4ec..0a0bbd184bec3 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -1711,6 +1711,15 @@ private static boolean isEmergencyNumberInternal(String number, numbers = numbers + SystemProperties.get(ecclist); } + // Additional emergency numbers can be set by a system property + String additionalEcclist = SystemProperties.get("ro.ril.ext.ecclist", null); + if (!TextUtils.isEmpty(additionalEcclist)) { + if (!TextUtils.isEmpty(numbers)) { + numbers = numbers + ","; + } + numbers = numbers + additionalEcclist; + } + if (TextUtils.isEmpty(numbers)) { // then read-only ecclist property since old RIL only uses this numbers = SystemProperties.get("ro.ril.ecclist"); From 6530cb8cccbf554abb318997d8c595f616247884 Mon Sep 17 00:00:00 2001 From: Eddy Witkamp Date: Fri, 22 Nov 2013 00:49:29 +0100 Subject: [PATCH 172/204] framework: NL translation Change-Id: I2ae5333aa41c6d582519c3bbc453268e6726b2de --- core/res/res/values-nl/cm_arrays.xml | 70 ++++++++++++++-------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/core/res/res/values-nl/cm_arrays.xml b/core/res/res/values-nl/cm_arrays.xml index 04b2d1529f715..5043aac6a9df9 100644 --- a/core/res/res/values-nl/cm_arrays.xml +++ b/core/res/res/values-nl/cm_arrays.xml @@ -17,40 +17,40 @@ - Probeert toegang te krijgen tot locatie - Probeert toegang te krijgen tot locatie - Probeert toegang te krijgen tot locatie - Probeert trillen te gebruiken - Probeert contacten te lezen - Probeert contacten aan te passen - Probeert oproeplogboek te lezen - Probeert oproeplogboek aan te passen - Probeert agenda te lezen - Probeert agenda aan te passen - Probeert toegang te krijgen tot locatie - Probeert melding te tonen - Probeert toegang te krijgen tot locatie - Probeert te bellen - Probeert sms/mms te lezen - Probeert sms/mms te schrijven/wijzigen - Probeert sms/mms te ontvangen - Probeert sms/mms te ontvangen - Probeert sms/mms te ontvangen - Probeert sms/mms te ontvangen - Probeert sms/mms te verzenden - Probeert sms/mms te lezen - Probeert sms/mms te schrijven/wijzigen - Probeert instellingen aan te passen - Probeert op de voorgrond te komen - Probeert toegang te krijgen tot meldingen - Probeert toegang te krijgen tot Camera - Probeert audio op te nemen - Probeert audio af te spelen - Probeert klembord te lezen - Probeert klembord aan te passen - Probeert wifi in/uit te schakelen - Probeert Bluetooth in/uit te schakelen - Probeert mobiele gegevens in/uit te schakelen - Probeert apparaat ontwaken in te plannen + probeert toegang te krijgen tot locatie + probeert toegang te krijgen tot locatie + probeert toegang te krijgen tot locatie + probeert trillen te gebruiken + probeert contacten te lezen + probeert contacten aan te passen + probeert oproeplogboek te lezen + probeert oproeplogboek aan te passen + probeert agenda te lezen + probeert agenda aan te passen + probeert toegang te krijgen tot locatie + probeert melding te tonen + probeert toegang te krijgen tot locatie + probeert te bellen + probeert sms/mms te lezen + probeert sms/mms te schrijven/wijzigen + probeert sms/mms te ontvangen + probeert sms/mms te ontvangen + probeert sms/mms te ontvangen + probeert sms/mms te ontvangen + probeert sms/mms te verzenden + probeert sms/mms te lezen + probeert sms/mms te schrijven/wijzigen + probeert instellingen aan te passen + probeert op de voorgrond te komen + probeert toegang te krijgen tot meldingen + probeert toegang te krijgen tot Camera + probeert audio op te nemen + probeert audio af te spelen + probeert klembord te lezen + probeert klembord aan te passen + probeert wifi in/uit te schakelen + probeert Bluetooth in/uit te schakelen + probeert mobiele gegevens in/uit te schakelen + probeert apparaat ontwaken in te plannen From 6a2cee4280070159d7b31bdff21c4bd1dcc7af0b Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Sat, 23 Nov 2013 08:00:08 +0000 Subject: [PATCH 173/204] PackageManager: Prevent themes from going into ASEC containers Themes on ASEC cause all kinds of random timing/racey issues at boot time, and more kinds of racey concurrency issues at uninstall/upgrade time. Stop them from getting into containers at all. Change-Id: If08e90c51137b22239831a4eca17ea00d5d87d93 --- core/java/android/content/pm/PackageInfoLite.java | 3 +++ core/java/android/content/pm/PackageParser.java | 14 ++++++++++++-- .../defcontainer/DefaultContainerService.java | 1 + .../android/server/pm/PackageManagerService.java | 8 +++++++- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/core/java/android/content/pm/PackageInfoLite.java b/core/java/android/content/pm/PackageInfoLite.java index a1566dadbadd1..8175acf3a0ca4 100644 --- a/core/java/android/content/pm/PackageInfoLite.java +++ b/core/java/android/content/pm/PackageInfoLite.java @@ -45,6 +45,7 @@ public class PackageInfoLite implements Parcelable { */ public int recommendedInstallLocation; public int installLocation; + public boolean isTheme; public VerifierInfo[] verifiers; @@ -66,6 +67,7 @@ public void writeToParcel(Parcel dest, int parcelableFlags) { dest.writeInt(versionCode); dest.writeInt(recommendedInstallLocation); dest.writeInt(installLocation); + dest.writeInt(isTheme ? 1 : 0); if (verifiers == null || verifiers.length == 0) { dest.writeInt(0); @@ -91,6 +93,7 @@ private PackageInfoLite(Parcel source) { versionCode = source.readInt(); recommendedInstallLocation = source.readInt(); installLocation = source.readInt(); + isTheme = source.readInt() == 1 ? true : false; final int verifiersLength = source.readInt(); if (verifiersLength == 0) { diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 057593a87444c..45b5b841c2502 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -205,12 +205,14 @@ public static class PackageLite { public final int versionCode; public final int installLocation; public final VerifierInfo[] verifiers; + public final boolean isTheme; public PackageLite(String packageName, int versionCode, - int installLocation, List verifiers) { + int installLocation, List verifiers, boolean isTheme) { this.packageName = packageName; this.versionCode = versionCode; this.installLocation = installLocation; + this.isTheme = isTheme; this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]); } } @@ -905,6 +907,7 @@ private static PackageLite parsePackageLite(Resources res, XmlPullParser parser, int installLocation = PARSE_DEFAULT_INSTALL_LOCATION; int versionCode = 0; int numFound = 0; + for (int i = 0; i < attrs.getAttributeCount(); i++) { String attr = attrs.getAttributeName(i); if (attr.equals("installLocation")) { @@ -924,6 +927,8 @@ private static PackageLite parsePackageLite(Resources res, XmlPullParser parser, final int searchDepth = parser.getDepth() + 1; final List verifiers = new ArrayList(); + boolean isTheme = false; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { @@ -936,9 +941,14 @@ private static PackageLite parsePackageLite(Resources res, XmlPullParser parser, verifiers.add(verifier); } } + + if (parser.getDepth() == searchDepth && "theme".equals(parser.getName())) { + isTheme = true; + installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY; + } } - return new PackageLite(pkgName.intern(), versionCode, installLocation, verifiers); + return new PackageLite(pkgName.intern(), versionCode, installLocation, verifiers, isTheme); } /** diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java index 09a25d01741ae..18e6b09d36364 100644 --- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java +++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java @@ -189,6 +189,7 @@ public PackageInfoLite getMinimalPackageInfo(final String packagePath, int flags ret.versionCode = pkg.versionCode; ret.installLocation = pkg.installLocation; ret.verifiers = pkg.verifiers; + ret.isTheme = pkg.isTheme; ret.recommendedInstallLocation = recommendAppInstallLocation(pkg.installLocation, packagePath, flags, threshold); diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 09d02cd012899..bd0448ba943d5 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -6836,6 +6836,9 @@ private int installLocationPolicy(PackageInfoLite pkgLite, int flags) { // reader synchronized (mPackages) { PackageParser.Package pkg = mPackages.get(packageName); + if (pkgLite.isTheme) { + return PackageHelper.RECOMMEND_INSTALL_INTERNAL; + } if (pkg != null) { if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { // Check for downgrading. @@ -7008,7 +7011,7 @@ public void handleStartCopy() throws RemoteException { loc = installLocationPolicy(pkgLite, flags); if (loc == PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE) { ret = PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE; - } else if (!onSd && !onInt) { + } else if ((!onSd && !onInt) || pkgLite.isTheme) { // Override install location with flags if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) { // Set the flag to install on external media. @@ -7020,6 +7023,9 @@ public void handleStartCopy() throws RemoteException { flags |= PackageManager.INSTALL_INTERNAL; flags &= ~PackageManager.INSTALL_EXTERNAL; } + if (pkgLite.isTheme) { + flags &= ~PackageManager.INSTALL_FORWARD_LOCK; + } } } } From 38e88ee4c64e00c68ea304f6b091a5ba245c0e5d Mon Sep 17 00:00:00 2001 From: Tamas Toth Date: Thu, 21 Nov 2013 08:46:13 +0100 Subject: [PATCH 174/204] core: HU translation PS2: Correcting PS3: Triggering Cid PS4: Typos PS7: Prepare for merging Change-Id: Ieeb8bf143f341e0d432a06e9eb86301d5a27a950 --- core/res/res/values-hu/cm_arrays.xml | 54 ++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 core/res/res/values-hu/cm_arrays.xml diff --git a/core/res/res/values-hu/cm_arrays.xml b/core/res/res/values-hu/cm_arrays.xml new file mode 100644 index 0000000000000..6ca04c4140151 --- /dev/null +++ b/core/res/res/values-hu/cm_arrays.xml @@ -0,0 +1,54 @@ + + + + + Megpróbál hozzáférni a helymeghatározáshoz + Megpróbál hozzáférni a helymeghatározáshoz + Megpróbál hozzáférni a helymeghatározáshoz + Megpróbálja használni a rezgő módot + Megpróbálja olvasni a névjegyeket + Megpróbálja módosítani a névjegyeket + Megpróbálja olvasni a hívásnaplót + Megpróbálja módosítani a hívásnaplót + Megpróbálja olvasni a naptárat + Megpróbálja módosítani a naptárat + Megpróbál hozzáférni a helymeghatározáshoz + Megpróbálja továbbitani a pozíciót + Megpróbál hozzáférni a helymeghatározáshoz + Megpróbál hívást indítani + Megpróbálja olvasni az SMS/MMS-eket + Megpróbálja írni/módosítani az SMS/MMS-eket + Megpróbálja fogadni az SMS/MMS-eket + Megpróbálja fogadni az SMS/MMS-eket + Megpróbálja fogadni az SMS/MMS-eket + Megpróbálja fogadni az SMS/MMS-eket + Megpróbálja küldeni az SMS/MMS-eket + Megpróbálja olvasni az SMS/MMS-eket + Megpróbálja írni/módosítani az SMS/MMS-eket + Megpróbálja módosítani a beállításokat + Megpróbál előtérbe kerülni + Megpróbál hozzáférni az értesítésekhez + Megpróbál hozzáférni a kamerához + Megpróbál hangot rögzíteni + Megpróbál hangot lejátszani + Megpróbálja olvasni a vágólapot + Megpróbálja módosítani a vágólapot + Megpróbálja ki/be kapcsolni a WiFi-t + Megpróbálja ki/be kapcsolni a Bluetooth-t + Megpróbálja ki/be kapcsolni a mobil adatkapcsolatot + Megpróbálja ütemezve felébreszteni az eszközt + + From 0c011a2ce85b7984f9a0d217367d018b9d35d9ad Mon Sep 17 00:00:00 2001 From: Ondrej Zima Date: Thu, 14 Nov 2013 12:08:38 +0100 Subject: [PATCH 175/204] FrameworkBase: CS translation - added AppOps - fixed AppOps for wakeup @CID: reexamine please Change-Id: I846a860974d8b2ff99e183001a673c379230de07 --- core/res/res/values-cs/cm_arrays.xml | 54 +++++++++++++++++++++++++++ core/res/res/values-cs/cm_strings.xml | 2 +- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 core/res/res/values-cs/cm_arrays.xml diff --git a/core/res/res/values-cs/cm_arrays.xml b/core/res/res/values-cs/cm_arrays.xml new file mode 100644 index 0000000000000..b7a90183acad6 --- /dev/null +++ b/core/res/res/values-cs/cm_arrays.xml @@ -0,0 +1,54 @@ + + + + + Pokus o získání pozice + Pokus o získání pozice + Pokus o získání pozice + Pokus o rying to use vibrate + Pokus o čtení kontaktů + Pokus o změnu kontaktů + Pokus o čtení seznamu hovorů + Pokus o změnu seznamu hovorů + Pokus o čtení kalendáře + Pokus o změnu kalendáře + Pokus o získání pozice + Pokus o odeslání upozornění + Pokus o získání pozice + Pokus o vytvoření telefonního hovoru + Pokus o čtení SMS/MMS + Pokus o uložení nebo změnu SMS/MMS + Pokus o přijmutí SMS/MMS + Pokus o přijmutí SMS/MMS + Pokus o přijmutí SMS/MMS + Pokus o přijmutí SMS/MMS + Pokus o odeslání SMS/MMS + Pokus o o čtení SMS/MMS + Pokus o uložení nebo změnu SMS/MMS + Pokus o změnu nastavení + Pokus o vykreslování do nejvyšší vrstvy + Pokus o přístup k upozorněním + Pokus o přístup k fotoaparátu + Pokus o nahrávání zvuku + Pokus o přehrávání zvuku + Pokus o načtení schránky + Pokus o změnu schránky + Pokus o přepnutí Wifi + Pokus o přepnutí Bluetooth + Pokus o přepnutí mobilních dat + Pokus o naplánování probuzení + + \ No newline at end of file diff --git a/core/res/res/values-cs/cm_strings.xml b/core/res/res/values-cs/cm_strings.xml index 13437f2ff54ee..7f7c020df8a57 100644 --- a/core/res/res/values-cs/cm_strings.xml +++ b/core/res/res/values-cs/cm_strings.xml @@ -24,6 +24,7 @@ Karta SIM je neplatná. Karta SIM/RUIM je zamčená Dotykem nastavit + Není dostupné žádné vyměnitelné médium\u2026 Požadavek USSD je změněn na požadavek DIAL. Požadavek USSD je změněn na požadavek SS. Požadavek USSD je změněn na nový požadavek USSD. @@ -62,7 +63,6 @@ Umožňuje zasílat SMS zprávy důvěryhodným aplikacím. Škodlivé aplikace mohou průběžně zasílat veliké množství zpráv a tím blokovat systém upozorňování a obtěžovat uživatele. Vybíjení - %d%% - Není dostupné žádné vyměnitelné médium\u2026 SD karta doku Aplikace ukončena Restartovat From 5eef1410d4a0ad837aa565a422ab0a5d9b759992 Mon Sep 17 00:00:00 2001 From: elektroschmock Date: Thu, 14 Nov 2013 20:13:14 +0100 Subject: [PATCH 176/204] Core: Update DE translation for AppOps Change-Id: I8319b7396a7f83a7ffcfb02df29187cc8e1dee23 --- core/res/res/values-de/cm_arrays.xml | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 core/res/res/values-de/cm_arrays.xml diff --git a/core/res/res/values-de/cm_arrays.xml b/core/res/res/values-de/cm_arrays.xml new file mode 100644 index 0000000000000..6ac4a707e6cb8 --- /dev/null +++ b/core/res/res/values-de/cm_arrays.xml @@ -0,0 +1,55 @@ + + + + + + Versucht den Standort abzurufen + Versucht den Standort abzurufen + Versucht den Standort abzurufen + Versucht Vibrationsalarm zu steuern + Versucht Kontakte zu lesen + Versucht Kontakte zu ändern + Versucht Anrufliste zu lesen + Versucht Anrufliste zu bearbeiten + Versucht Kalendereinträge zu lesen + Versucht Kalendereinträge zu ändern + Versucht den Standort abzurufen + Versucht Benachrichtigung zu erstellen + Versucht den Standort abzurufen + Versucht Anrufe zu tätigen + Versucht SMS/MMS zu lesen + Versucht SMS/MMS zu ändern + Versucht SMS/MMS zu empfangen + Versucht SMS/MMS zu empfangen + Versucht SMS/MMS zu empfangen + Versucht SMS/MMS zu empfangen + Versucht SMS/MMS zu senden + Versucht SMS/MMS zu senden + Versucht SMS/MMS zu ändern + Versucht Einstellungen zu ändern + Versucht an oberste Position zu ziehen + Versucht auf Benachrichtigungen zuzugreifen + Versucht Bilder und Videos aufzunehmen + Versucht Audio aufzunehmen + Versucht Audio wiedergeben + Versucht Zwischenablage zu lesen + Versucht Zwischenablage zu ändern + Versucht WLAN ein-/auszuschalten + Versucht Bluetooth ein-/auszuschalten + Versucht mobile Daten ein-/auszuschalten + Versucht den Ruhezustand zu deaktivieren + + From 3d585059d7410c26a542aa5d5534c4f65898e54c Mon Sep 17 00:00:00 2001 From: Naveen Kalla Date: Wed, 3 Jul 2013 16:39:27 -0700 Subject: [PATCH 177/204] Set subscription_mode in the database to a default value If ro.telephony.default_cdma_sub is set, use that to set the default CDMA subscription source in the database. If that is not set use the default preferred value defined in the source code. Change-Id: I11fff596a5fe721c64f192c889672326517dc43d --- core/java/android/provider/Settings.java | 9 --------- .../com/android/providers/settings/DatabaseHelper.java | 9 ++++++++- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 29ad4b30eb88e..cad29bd8169b0 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3788,7 +3788,6 @@ public static final class Secure extends NameValueTable { MOVED_TO_GLOBAL.add(Settings.Global.SET_GLOBAL_HTTP_PROXY); MOVED_TO_GLOBAL.add(Settings.Global.DEFAULT_DNS_SERVER); MOVED_TO_GLOBAL.add(Settings.Global.PREFERRED_NETWORK_MODE); - MOVED_TO_GLOBAL.add(Settings.Global.PREFERRED_CDMA_SUBSCRIPTION); } /** @hide */ @@ -6517,14 +6516,6 @@ public static final String getBluetoothInputDevicePriorityKey(String address) { public static final String PREFERRED_NETWORK_MODE = "preferred_network_mode"; - /** - * The cdma subscription 0 = Subscription from RUIM, when available - * 1 = Subscription from NV - * @hide - */ - public static final String PREFERRED_CDMA_SUBSCRIPTION = - "preferred_cdma_subscription"; - /** * Name of an application package to be debugged. */ diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java index 75f25f4973242..06540e1a791c3 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java @@ -51,6 +51,7 @@ import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.RILConstants; +import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager; import com.android.internal.util.XmlUtils; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternView; @@ -1435,7 +1436,7 @@ public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) { }; String[] secureToGlobal = { Settings.Global.PREFERRED_NETWORK_MODE, - Settings.Global.PREFERRED_CDMA_SUBSCRIPTION, + Settings.Global.CDMA_SUBSCRIPTION_MODE, }; moveSettingsToNewTable(db, TABLE_SYSTEM, TABLE_GLOBAL, systemToGlobal, true); @@ -2317,6 +2318,12 @@ private void loadGlobalSettings(SQLiteDatabase db) { } loadSetting(stmt, Settings.Global.PREFERRED_NETWORK_MODE, val); + // Set the preferred cdma subscription source to target desired value or default + // value defined in CdmaSubscriptionSourceManager + type = SystemProperties.getInt("ro.telephony.default_cdma_sub", + CdmaSubscriptionSourceManager.PREFERRED_CDMA_SUBSCRIPTION); + loadSetting(stmt, Settings.Global.CDMA_SUBSCRIPTION_MODE, type); + // --- New global settings start here } finally { if (stmt != null) stmt.close(); From 0411dcf42716bad8e51e092c50664ff53837a91b Mon Sep 17 00:00:00 2001 From: Michael Bestas Date: Thu, 28 Nov 2013 03:51:09 +0200 Subject: [PATCH 178/204] mdpi: Override only the required dimensions We should only override whatever dimension is needed Should fix the lockscreen targets icon size changed here: http://review.cyanogenmod.org/31987 Change-Id: I602e8d3c2b501a2b8df56a1855c9279b67a767f8 --- core/res/res/values-mdpi/dimens.xml | 329 ---------------------------- 1 file changed, 329 deletions(-) diff --git a/core/res/res/values-mdpi/dimens.xml b/core/res/res/values-mdpi/dimens.xml index 27786e20774e9..51570c6ca254d 100644 --- a/core/res/res/values-mdpi/dimens.xml +++ b/core/res/res/values-mdpi/dimens.xml @@ -18,335 +18,6 @@ */ --> - - 164dp - - 145dp - - 48dip - - 2 - 64dip - - 25dip - - 48dp - - 48dp - - 42dp - - 24dip - - 48sp - - @dimen/navigation_bar_height - - 32dip - - 5dp - - - 104dp - - 64dp - - 52dp - - 800dp - - - 56dip - - 56dip - - 4dip - - 3dip - - 9dip - - - 270dp - - - 135dip - - - 75dip - - - 40dip - - - 15dip - - - 0dp - - 0dp - - 0dp - - 0dp - - 48dp - - 0dp - - 16dp - - 4 - - 6 - - 0dp - - 0dp - - 0dp - - 65% - - - 320dp - - 320dp - - 80% - - 100% - - - 0dp - - 16dip - 0x02000000 - - 0x02000000 - - 8dip - 8dip - 16dip - - - 95% - - - 64dp - - 64dp - - - 160dip - - - 320dip - - - 64dip - - 48dip - - - 48dip - - 8dip - - 18dp - - 14dp - - -3dp - - 5dip - - - 80dip - - - 14dip - - - 42dip - - - 22dip - - - 12dip - - - 40dip - - - 330dip - - - 200dip - - - 8dip - - - 8dip - - - 8dip - - - 32dip - - - 240dip - - - 80dp - - - 8dp - 8dp - 8dp - 8dp - - - 56dip - - - 48dp - - - 180dp - - - 14dp - - 18dp - - 12dp - - - 25dp - - - - 600dp - - - 480dp - - - 0dp - - - 0dp - - - 75dp - - - 15dp - - - 13dp - - - 16dp - - - -16dp - - - 0dp - - - 0dp - - - 60dp - - - 46dp - - - 7dp - - - 2dp - - - 16dp - - - 0dp - - - 64dp - - - 0dp - - - 80dip - - - 320dp - 300dp - - - 450dp - - - 8dp - - - 8dp - - - 2dp - - - 1dp - - - 66dp - - - 10sp - - - 24dp - - - 600dp - - - 160dp - - - 10dp - From ccf72b3cae8d18de65acfccc374719f567b23b11 Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Thu, 28 Nov 2013 07:41:02 -0800 Subject: [PATCH 179/204] Fix resource id of networkAttributes * Google didn't make networkAttributes a public resource, so everyone is failing CTS after adding new resources to the framework. This fixes it. Change-Id: I1fdade47098bc9030116230dce27a3e6e5aab413 --- core/res/res/values/public.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index a5ebaf3466b71..7497f5a1b4196 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -733,6 +733,11 @@ + + + From e63e4d160a358e485be42ea1c9da0766ea146bc6 Mon Sep 17 00:00:00 2001 From: Ricardo Cerqueira Date: Thu, 28 Nov 2013 21:03:13 +0000 Subject: [PATCH 180/204] api: Add networkAttributes to the public resource list Companion change to I1fdade47098bc9030116230dce27a3e6e5aab413 Change-Id: I54a95f1748d7b60be0c15a9a2f7f7badc13cbbd8 --- api/current.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/api/current.txt b/api/current.txt index 71d634668f8cd..bab258986aa5c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -208,6 +208,7 @@ package android { ctor public R.array(); field public static final int emailAddressTypes = 17235968; // 0x1070000 field public static final int imProtocols = 17235969; // 0x1070001 + field public static final int networkAttributes = 17235989; // 0x1070015 field public static final int organizationTypes = 17235970; // 0x1070002 field public static final int phoneTypes = 17235971; // 0x1070003 field public static final int postalAddressTypes = 17235972; // 0x1070004 From 7f66ca6f0ab4128909f7afaa6da6c4526db4386d Mon Sep 17 00:00:00 2001 From: kaiyiz Date: Mon, 4 Nov 2013 10:07:24 +0800 Subject: [PATCH 181/204] WMS: fix no thumbnail image of Gallery in the recent tasks list. When it takes the screenshot of an application, it will calculate the minLayer and maxLayer first, and if a window is full screen, it won't deal with the windows below it. However, the surfaceview is placed below a window but will be displayed at front, this make the surface view can not be included when take the screenshot of an application, then it diaplays a black area in the recent tasks list. If the currect window is full screen, no need to finish the calculation. CR-Fixed:566752 Change-Id: Iaf3e9a3e6520007571ea545ccc9c05d4b1b416fd --- .../java/com/android/server/wm/WindowManagerService.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 9840418680cd0..2124c5974d83b 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -5442,11 +5442,6 @@ public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, ws.isDisplayedLw()) { screenshotReady = true; } - - if (fullscreen) { - // No point in continuing down through windows. - break; - } } if (appToken != null && appWin == null) { From 97237913131f5e8c60db1ba9a3d41a7b8b99e7e5 Mon Sep 17 00:00:00 2001 From: arnau Date: Sat, 30 Nov 2013 14:37:29 +0100 Subject: [PATCH 182/204] Core: CA translations Change-Id: I200732d3c576bdf8044192d2442678f5d4d8e61d --- core/res/res/values-ca/cm_arrays.xml | 55 +++++++++++++++++++ core/res/res/values-ca/cm_strings.xml | 3 + .../InputDevices/res/values-ca/cm_strings.xml | 20 +++++++ 3 files changed, 78 insertions(+) create mode 100644 core/res/res/values-ca/cm_arrays.xml create mode 100644 packages/InputDevices/res/values-ca/cm_strings.xml diff --git a/core/res/res/values-ca/cm_arrays.xml b/core/res/res/values-ca/cm_arrays.xml new file mode 100644 index 0000000000000..7eb1f2848200e --- /dev/null +++ b/core/res/res/values-ca/cm_arrays.xml @@ -0,0 +1,55 @@ + + + + + + Intentant accedir a l\'ubicació + Intentant accedir a l\'ubicació + Intentant accedir a l\'ubicació + Intentant utilitzar la vibració + Intentant llegir els contactes + Intentant modificar els contactes + Intentant llegir el registre de trucades + Intentant modificar el registre de trucades + Intentant llegir el calendari + Intentant modificar el calendari + Intentant accedir a l\'ubicació + Intentant publicar una notificació + Intentant accedir a l\'ubicació + Intentant fer una trucada de telèfon + Intentant llegir SMS/MMS + Intentant escriure/modificar SMS/MMS + Intentant rebre SMS/MMS + Intentant rebre SMS/MMS + Intentant rebre SMS/MMS + Intentant rebre SMS/MMS + Intentant enviar SMS/MMS + Intentant llegir SMS/MMS + Intentant escriure/modificar SMS/MMS + Intentant modificar ajustaments + Intentant dibuixar a sobre + Intentant accedir a les notificacions + Intentant accedir Càmera + Intentant enregistrar audio + Intentant reproduir audio + Intentant llegir el portapapers + Intentant modificar el portapapers + Intentant activar/desactivar Wifi + Intentant activar/desactivar bluetooth + Intentant activar/desactivar dades mòbils + Intentant programar despertar el dispositiu + + diff --git a/core/res/res/values-ca/cm_strings.xml b/core/res/res/values-ca/cm_strings.xml index b841195484e97..666b414be161d 100644 --- a/core/res/res/values-ca/cm_strings.xml +++ b/core/res/res/values-ca/cm_strings.xml @@ -141,4 +141,7 @@ La petició SS està modificada a una nova petició SS. SUB:%d : %s. %s, %s + Estalvi d\'energia + Equilibrat + Rendiment diff --git a/packages/InputDevices/res/values-ca/cm_strings.xml b/packages/InputDevices/res/values-ca/cm_strings.xml new file mode 100644 index 0000000000000..a0b6daefdce85 --- /dev/null +++ b/packages/InputDevices/res/values-ca/cm_strings.xml @@ -0,0 +1,20 @@ + + + + Anglès (EUA), estil Colemak + Armeni de l\'Est + From 5655bc00648f4053347742daaa740e7378713c12 Mon Sep 17 00:00:00 2001 From: Vladislav Koldobskiy Date: Sat, 30 Nov 2013 22:02:51 +0400 Subject: [PATCH 183/204] Core & SystemUI: RU translation Fix ALL the translations! Includes plurals' fix (cause I'm tired of wrong timestamps here and there) Change-Id: If5ce60a421d3fcdf4836f5312b5205a6b11ba3f7 --- core/res/res/values-ru/cm_arrays.xml | 56 +++++++++ core/res/res/values-ru/cm_strings.xml | 12 +- core/res/res/values-ru/strings.xml | 114 +++++++++--------- .../SystemUI/res/values-ru/cm_strings.xml | 8 +- packages/SystemUI/res/values-ru/strings.xml | 6 +- 5 files changed, 127 insertions(+), 69 deletions(-) create mode 100644 core/res/res/values-ru/cm_arrays.xml diff --git a/core/res/res/values-ru/cm_arrays.xml b/core/res/res/values-ru/cm_arrays.xml new file mode 100644 index 0000000000000..f0b65d557b3c6 --- /dev/null +++ b/core/res/res/values-ru/cm_arrays.xml @@ -0,0 +1,56 @@ + + + + + + + попытка получения доступа к данным о местоположении + попытка получения доступа к данным о местоположении + попытка получения доступа к данным о местоположении + попытка использования вибрации + попытка чтения данных контактов + попытка изменения контактов + попытка просмотра списка вызовов + попытка изменения списка вызовов + попытка чтения данных календаря + попытка изменения календаря + попытка получения доступа к данным о местоположении + попытка вывода уведомления + попытка получения доступа к данным о местоположении + попытка выполнения телефонного звонка + попытка чтения SMS/MMS + попытка записи SMS/MMS + попытка получения SMS/MMS + попытка получения SMS/MMS + попытка получения SMS/MMS + попытка получения SMS/MMS + попытка отправки SMS/MMS + попытка чтения SMS/MMS + попытка записи SMS/MMS + попытка изменения настроек + попытка отображения поверх других элементов + попытка получения доступа к уведомлениям + попытка использования камеры + попытка записи аудио + попытка воспроизведения аудио + попытка чтения буфера обмена + попытка изменения буфера обмена + попытка включения или выключения Wi-Fi + попытка включения или выключения Bluetooth + попытка включения или выключения Мобильного интернета + попытка создания таймера пробуждения устройства + + diff --git a/core/res/res/values-ru/cm_strings.xml b/core/res/res/values-ru/cm_strings.xml index 4f5156e1ce1c9..4f3c42af18cf4 100644 --- a/core/res/res/values-ru/cm_strings.xml +++ b/core/res/res/values-ru/cm_strings.xml @@ -45,14 +45,14 @@ Поворот экрана разблокирован Поворот экрана заблокирован %s не установлено - Включение или выключение режима инкогнито - Приложение может выбрать, будет ли другое приложение работать в режиме инкогнито. Когда приложение запущено в режиме инкогнито, оно не получает доступ к персональным данным, таким как контакты, сообщения или журнал звонков. - Режим инкогнито активен - %1$s не сможет получать доступ к персональным данным + Включение или выключение защищённого режима + Приложение может выбрать, будет ли другое приложение работать в защищённом режиме. Когда приложение запущено в защищённом режиме, оно не получает доступ к персональным данным, таким как контакты, сообщения или журнал звонков. + Защищённый режим включён + «%1$s» не имеет доступа к персональным данным Профили Не выбран - Отключение уведомлений - Разрешить приложению отключать уведомления, созданные другими приложениями. + Удаление уведомлений + Разрешить приложению удалять уведомления, созданные другими приложениями. Перехват исходящих SMS Разрешить приложению перехватывать исходящие SMS. Вредоносные приложения смогут использовать это, чтобы препятствовать отправке SMS-сообщений. Показ фиктивных SMS-сообщений diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index c6b77d5e88278..08e5e8dc11763 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -288,7 +288,7 @@ "Изменение настроек экрана" "Приложение сможет изменять текущую конфигурацию, например, региональные настройки или размер шрифта." "Включение режима громкой связи" - "Приложение сможет включать режим \"Штурман\"." + "Приложение сможет включать режим «Штурман»." "Закрытие других приложений" "Приложение сможет завершать фоновые процессы других приложений. Из-за этого другие приложения могут прекратить работу." "Принудительное закрытие других приложений" @@ -590,7 +590,7 @@ "Отключение функции блокировки экрана" "Приложение сможет отключать блокировку экрана и другие функции защиты. Например, блокировка экрана будет отключаться при получении входящего вызова и включаться после завершения разговора." "Просмотр настроек синхронизации" - "Приложение сможет просматривать настройки синхронизации аккаунта, например определять, включена ли синхронизация для приложения \"Контакты\"." + "Приложение сможет просматривать настройки синхронизации аккаунта, например определять, включена ли синхронизация для приложения «Контакты»." "Включение/выключение синхронизации" "Приложение сможет изменять настройки синхронизации аккаунта. Например, с помощью этого разрешения можно включить в аккаунте синхронизацию контактов." "Просмотр статистики синхронизации" @@ -773,12 +773,12 @@ "Введите пароль" "Введите PIN-код" "Неверный PIN-код." - "Для разблокировки нажмите \"Меню\", а затем 0." + "Для разблокировки нажмите «Меню», а затем 0." "Экстренная служба" "Нет сигнала" "Экран заблокирован." - "Нажмите \"Меню\", чтобы разблокировать экран или вызвать службу экстренной помощи." - "Для разблокировки нажмите \"Меню\"." + "Нажмите «Меню», чтобы разблокировать экран или вызвать службу экстренной помощи." + "Для разблокировки нажмите «Меню»." "Введите графический ключ" "Экстренный вызов" "Вернуться к вызову" @@ -841,7 +841,7 @@ "Пусто" "Область разблокировки развернута" "Область разблокировки свернута" - "Виджет \"%1$s\"" + "Виджет «%1$s»" "Выбор аккаунта" "Статус" "Камера" @@ -904,7 +904,7 @@ "Установка будильника" "Приложение сможет настраивать будильник. Функция поддерживается не во всех программах." "Добавление голосовых сообщений" - "Приложение сможет добавлять голосовые сообщения в папку \"Входящие\"." + "Приложение сможет добавлять голосовые сообщения в папку «Входящие»." "Изменение прав доступа к геоданным в браузере" "Приложение сможет изменять настройки доступа к геоданным в браузере. Вредоносные программы смогут таким образом отправлять информацию о местоположении на любые веб-сайты." "Проверка пакетов" @@ -934,22 +934,25 @@ "Удалить запрос" "Отправить запрос" "Голосовой поиск" - "Включить \"Изучение касанием\"?" - "%1$s хочет включить функцию \"Изучение касанием\". Она позволяет прослушивать или просматривать описание элементов, которых вы касаетесь, и управлять планшетным ПК с помощью жестов." - "%1$s хочет включить функцию \"Изучение касанием\". Она позволяет прослушивать или просматривать описание элементов, которых вы касаетесь, и управлять телефоном с помощью жестов." + "Включить «Изучение касанием»?" + "%1$s хочет включить функцию «Изучение касанием». Она позволяет прослушивать или просматривать описание элементов, которых вы касаетесь, и управлять планшетным ПК с помощью жестов." + "%1$s хочет включить функцию «Изучение касанием». Она позволяет прослушивать или просматривать описание элементов, которых вы касаетесь, и управлять телефоном с помощью жестов." "1 месяц назад" "Более месяца назад" - "1 секунду назад" - "%d с. назад" + "%d секунду назад" + "%d секунды назад" + "%d секунд назад" - "1 минуту назад" - "%d мин. назад" + "%d минуту назад" + "%d минуты назад" + "%d минут назад" - "1 час назад" - "%d ч. назад" + "%d час назад" + "%d часа назад" + "%d часов назад" "Последние %d дн." @@ -961,12 +964,14 @@ "%d дн. назад" - "через 1 секунду" - "через %d с." + "через %d секунду" + "через %d секунды" + "через %d секунд" - "через 1 минуту" - "через %d мин." + "через %d минуту" + "через %d минуты" + "через %d минут" "через 1 час" @@ -977,15 +982,12 @@ "через %d дн." - "1 сек. назад" "%d сек. назад" - "1 мин. назад" "%d мин. назад" - "1 час назад" "%d ч. назад" @@ -993,15 +995,12 @@ "%d дн. назад" - "через 1 с." "через %d с." - "через 1 мин." "через %d мин." - "через 1 час" "через %d ч." @@ -1024,16 +1023,19 @@ "г." "г." - "1 сек." - "%d сек." + "%d секунда" + "%d секунды" + "%d секунд" - "1 мин." - "%d мин." + "%d минута" + "%d минуты" + "%d минут" - "1 ч." - "%d ч." + "%d час" + "%d часы" + "%d часов" "Ошибка" "Это видео не предназначено для потокового воспроизведения на данном устройстве." @@ -1061,7 +1063,7 @@ "Операции с текстом" "Заканчивается свободное место" "Некоторые системные функции могут не работать" - "Приложение \"%1$s\" выполняется" + "Приложение «%1$s» выполняется" "Нажмите, чтобы получить дополнительные данные или выключить приложение." "ОК" "Отмена" @@ -1069,24 +1071,24 @@ "Отмена" "Внимание" "Загрузка…" - "I" - "O" + "\u2759" +"\u3007" "Что использовать?" "По умолчанию для этого действия" - "Удаляет настройки по умолчанию в меню \"Настройки > Приложения > Загруженные\"." + "Удаляет настройки по умолчанию в меню «Настройки > Приложения > Загруженные»." "Выберите действие" "Выбор приложения для USB-устройства" "Действие не поддерживается ни в одном приложении." - "В приложении \"%1$s\" произошла ошибка." - "В приложении \"%1$s\" произошла ошибка." + "В приложении «%1$s» произошла ошибка." + "В работе процесса «%1$s» произошла ошибка." - "Приложение \"%2$s\" не отвечает."\n\n"Закрыть его?" - "Приложение \"%1$s\" не отвечает."\n\n"Закрыть его?" - "Приложение \"%1$s\" не отвечает. Закрыть его?" - "Приложение \"%1$s\" не отвечает."\n\n"Закрыть его?" + "Приложение «%2$s» не отвечает."\n\n"Закрыть его?" + "Процесс «%1$s» не отвечает."\n\n"Завершить его?" + "Процесс приложения «%1$s» не отвечает. Завершить его?" + "Процесс «%1$s» не отвечает."\n\n"Завершить его?" "ОК" - "Отзыв" + "Сообщить" "Подождать" "Страница не отвечает."\n\n"Закрыть ее?" "Приложение перенаправлено" @@ -1094,8 +1096,8 @@ "Изначально было запущено приложение %1$s." "Масштаб" "Всегда показывать" - "Включить эту функцию можно в меню \"Настройки > Приложения > Загруженные\"." - "Приложение \"%1$s\" (процесс: %2$s) нарушило собственную политику StrictMode." + "Включить эту функцию можно в меню «Настройки > Приложения > Загруженные»." + "Приложение «%1$s» (процесс: %2$s) нарушило собственную политику StrictMode." "Процесс %1$s нарушил собственную политику StrictMode." "Обновление Android..." "Оптимизация приложения %1$d из %2$d." @@ -1113,7 +1115,7 @@ "Громкость звонка" "Громкость мультимедиа" "Воспроизведение по каналу Bluetooth" - "Выбран режим \"Без звука\"" + "Выбран режим «Без звука»" "Громкость при разговоре" "Громкость при разговоре" "Громкость сигнала предупреждения" @@ -1163,19 +1165,19 @@ "<b>%1$s</b> отправляет большое количество SMS. Разрешить приложению и дальше отправлять сообщения?" "Разрешить" "Запретить" - "Приложение <b>%1$s</b> собирается отправить сообщение на адрес <b>%2$s</b>." + "Приложение «<b>%1$s</b>» собирается отправить сообщение на номер <b>%2$s</b>." "С вашего мобильного счета ""могут быть списаны средства""." "С вашего мобильного счета будут списаны средства." "Отправить" "Отмена" "Запомнить выбранный телефон" - "Это можно изменить позже в разделе настроек \"Приложения\"." + "Это можно изменить позже в разделе настроек «Приложения»." "Всегда разрешать" "Не разрешать" - "SIM-карта удалена" + "SIM-карта извлечена" "Пока вы не вставите действующую SIM-карту, мобильная сеть будет недоступна." "Готово" - "SIM-карта добавлена" + "SIM-карта установлена" "Перезагрузите устройство для доступа к мобильной сети." "Перезапуск" "Настройка времени" @@ -1221,7 +1223,7 @@ "Выберите способ ввода" "Настройка способов ввода" "Физическая клавиатура" - "Аппаратура" + "Устройство" "Выберите раскладку клавиатуры" "Нажмите, чтобы выбрать раскладку клавиатуры." " ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -1264,7 +1266,7 @@ "Отправить" "Далее" "Готово" - "Пред." + "Назад" "Выполнить" "Набрать номер"\n"%s" "Создать контакт"\n"с номером %s" @@ -1273,7 +1275,7 @@ "Запрос доступа" "Разрешить" "Отклонить" - "Разрешение запрошено" + "Запрос разрешения" "Требуется разрешение"\n"для аккаунта %s." "Способ ввода" "Синхр." @@ -1293,7 +1295,7 @@ "Не выбран файл" "Сбросить" "Отправить" - "Включен режим \"Штурман\"" + "Включен режим «Штурман»" "Чтобы выйти, нажмите здесь." "USB-модем/точка доступа Wi-Fi используется" "Нажмите для настройки." @@ -1367,7 +1369,7 @@ "Клавиша ввода" "Выберите приложение" "Открыть доступ:" - "Открыть доступ приложению \"%s\"" + "Открыть доступ приложению «%s»" "Перетаскиваемый значок блокировки. Нажмите и удерживайте." "Проведите вверх, чтобы %s." "Проведите вниз, чтобы %s." @@ -1394,7 +1396,7 @@ "Проверьте трафик и настройки." "Передача данных 2G/3G отключена" "Передача данных 4G отключена" - "Моб. Интернет отключен" + "Моб. интернет отключен" "Передача данных через Wi-Fi отключена" "Нажмите, чтобы включить." "Превышен лимита трафика 2G и 3G" diff --git a/packages/SystemUI/res/values-ru/cm_strings.xml b/packages/SystemUI/res/values-ru/cm_strings.xml index 7d486e402dd67..f5ea5c654caed 100644 --- a/packages/SystemUI/res/values-ru/cm_strings.xml +++ b/packages/SystemUI/res/values-ru/cm_strings.xml @@ -21,7 +21,7 @@ Заряжено Профиль GPS выкл. - Сон + Выключить экран Вкл. звук Выкл. звук Вкл. вибро @@ -30,7 +30,7 @@ Выкл. Звук Экран блокировки - Тип сети + Режим сети Отчёт об ошибке Синхронизация Синхронизация выкл. @@ -48,8 +48,8 @@ LTE выкл. Громкость Камера - ADB по сети выкл. - ADB по сети + Отладка выкл. + Отладка по сети Расширенный Обычный Выберите действие diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index d1a9ecd7fadd5..11b6c71a183bf 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -49,8 +49,8 @@ "Общий модем доступен через Bluetooth" "Настройка способов ввода" "Физическая клавиатура" - "Открыть приложению \"%1$s\" доступ к USB-устройству?" - "Открыть приложению \"%1$s\" доступ к USB-устройству?" + "Открыть приложению «%1$s» доступ к USB-устройству?" + "Открыть приложению «%1$s» доступ к USB-устройству?" "Запускать %1$s при подключении этого USB-устройства?" "Запускать %1$s при подключении этого USB-аксессуара?" "Приложения не поддерживают это USB-устройство. Подробнее о нем читайте здесь: %1$s." @@ -146,7 +146,7 @@ "Телетайп включен." "Вибровызов." "Беззвучный режим." - "Приложение \"%s\" удалено из списка." + "Приложение «%s» удалено из списка." "Уведомление закрыто" "Панель уведомлений" "Быстрые настройки" From 55c017362991894fa1c930234487ddc02090f7c1 Mon Sep 17 00:00:00 2001 From: Frant1c Date: Sun, 10 Nov 2013 21:23:47 -0500 Subject: [PATCH 184/204] Update Lithuanian translations Change-Id: I4cbe3e6ff29dfecfb3a4a8b1e7566bdfda42e5d2 --- core/res/res/values-lt/cm_arrays.xml | 54 +++++++++++ core/res/res/values-lt/cm_strings.xml | 94 +++++++++++++++++++ .../InputDevices/res/values-lt/cm_strings.xml | 50 ++++++++++ .../SystemUI/res/values-lt/cm_strings.xml | 76 +++++++++++++++ 4 files changed, 274 insertions(+) create mode 100644 core/res/res/values-lt/cm_arrays.xml create mode 100644 core/res/res/values-lt/cm_strings.xml create mode 100644 packages/InputDevices/res/values-lt/cm_strings.xml create mode 100644 packages/SystemUI/res/values-lt/cm_strings.xml diff --git a/core/res/res/values-lt/cm_arrays.xml b/core/res/res/values-lt/cm_arrays.xml new file mode 100644 index 0000000000000..5c2fb8bfaffc3 --- /dev/null +++ b/core/res/res/values-lt/cm_arrays.xml @@ -0,0 +1,54 @@ + + + + + Bando pasiekti vietovę + Bando pasiekti vietovę + Bando pasiekti vietovę + Bando naudotis vibracija + Bando skaityti kontaktus + Bando keisti kontaktus + Bando skaityti skambučių žurnalą + Bando keisti skambučių žurnalą + Bando skaityti kalendorių + Bando keisti kalendorių + Bando pasiekti vietovę + Bando rašyti pranešimą + Bando pasiekti vietovę + Bando skambinti telefonu + Bando skaityti SMS/MMS + Bando rašyti/keisti SMS/MMS + Bando gauti SMS/MMS + Bando gauti SMS/MMS + Bando gauti SMS/MMS + Bando gauti SMS/MMS + Bando siųsti SMS/MMS + Bando skaityti SMS/MMS + Bando rašyti/keisti SMS/MMS + Bando keisti nustatymus + Bando piešti viršuje + Bando pasiekti pranešimus + Bando pasiekti kamera + Bando įrašyti garso įrašą + Bando groti garso įrašą + Bando skaityti iškarpinę + Bando keisti iškarpinę + Bando įjungti/išjungti Wifi + Bando įjungti/išjungti bluetooth + Bando įjungti/išjungti mobiliuosius duomenis + Bando planuoti kada įrenginys pabus + + diff --git a/core/res/res/values-lt/cm_strings.xml b/core/res/res/values-lt/cm_strings.xml new file mode 100644 index 0000000000000..6b98d2928d4b8 --- /dev/null +++ b/core/res/res/values-lt/cm_strings.xml @@ -0,0 +1,94 @@ + + + + Numatytasis + Darbas + Namai + Tylus + Naktis + Telefonas + Kalendorius + Gmail + El. paštas + Pranešimai + Perkrauti planšetinį kompiuterį + Perkrauti telefoną + Ekranvaizdis + Išplėstas darbalaukis + Įjungta + Išjungta + Perkrauti + Atkūrimo režimas + \'Bootloader\' + Įjungimo meniu + Greitasis įjungimas + Parsisiuntimo režimas + Perkraunama\u2026 + Jūsų planšetinis kompiuteris persikraus. + Jūsų telefonas persikraus. + Kitas + Perkrauti + Profilis + Ekrano sukimas atrakintas + Ekrano sukimas užrakintas + Programa priverstinai uždaryta + %s nėra įdiegta + Nepaisyti įjungimo klavišo + Leisti programoms nepaisyti įjungimo klavišo + Kontroliuoti FM imtuvą + Leidžia programai valdyti FM imtuvą + Kontroliuoti FM siųstuvą + Leidžia programai valdyti FM siųstuvą + Įjungti arba išjungti privatumo apsaugą + Leisti programai keisti, kai kita programa veikia su privatumo apsauga. Kai programa veikia su privatumo apsauga ji neturės prieigos prie asmeninių duomenų, pavyzdžiui, kontaktų, skambučių žurnalų ar pranešimų. + Perimti siunčiamus SMS + Leisti programai perimti siunčiamus SMS. Kenkėjiškos programos gali tuo pasinaudoti, kad būtų užkirstas kelias siunčiamiems SMS. + Atšaukti programos įspėjimus + Leidžia programai atšaukti įspėjimus, sukurtus kitų programų. + Privatumo apsauga aktyvi + %1$s negalės naudotis asmeniniais duomenimis + Profiliai + Nėra + Iškraunama, %d%% + Atminties kortelės dokas + Siųsti netikrus pranešimus + Leidžia programai siųsti netikrus pranešimus. Tai leidžia programai siųsti pranešimus patikimoms programoms. Kenkėjiškos programos gali siųsti pranešimus nuolat, blokuodamos įrenginio įspėjimų sistemą ir sutrikdant vartotoją + Laikmenos nėra\u2026 + Užtikrinti SELinux + Perjungti SELinux politiką tarp vykdančiojo arba liberalaus. + Užtikrinti MMAC + Perjungti MMAC politiką tarp vykdančiojo arba liberalaus. + Energijos taupymas + Subalansuotas + Našumas + Nesėkmingas. Įjunkite SIM/RUIM Užraktą. + Neteisingas PUK kodas! + PIN operacija nepavyko! + PUK operacija nepavyko! + Kodas priimtas! + \nLikę bandymai : + Negaliojanti kortelė. + Negaliojanti SIM kortelė. + SIM/RUIM kortelė yra užrakinta. + USSD užklausa pakeista dėl DIAL prašymo. + USSD užklausa pakeista dėl SS prašymo. + USSD užklausa pakeista į naują. + SS užklausa pakeista į naują DIAL prašymą. + SS užklausa pakeista į naują USSD prašymą. + SS užklausa pakeista į naują. + SUB:%d : %s. + %s, %s + diff --git a/packages/InputDevices/res/values-lt/cm_strings.xml b/packages/InputDevices/res/values-lt/cm_strings.xml new file mode 100644 index 0000000000000..1ad774f35711d --- /dev/null +++ b/packages/InputDevices/res/values-lt/cm_strings.xml @@ -0,0 +1,50 @@ + + + + Įvesties įrenginiai + Klaviatura Android + Anglų (JK) + Anglų (JAV) + Anglų (JAV), Colemak stilius + Anglų (JAV), Dvorak stilius + Vokiečių + Prancūzų + Prancūzų (Kanada) + Rusų + Rusų, Mac stilius + Ispanų + Šveicarijos Prancūzų + Šveicarijos Vokiečių + Belgų + Bulgarų + Italų + Danų + Norvegų + Švedų + Suomių + Kroatų + Čekų + Estų + Vengrų + Islandų + Portugalų + Slovakų + Slovėnų + Turkų + Ukrainiečių + Armėnų + diff --git a/packages/SystemUI/res/values-lt/cm_strings.xml b/packages/SystemUI/res/values-lt/cm_strings.xml new file mode 100644 index 0000000000000..693c900dde718 --- /dev/null +++ b/packages/SystemUI/res/values-lt/cm_strings.xml @@ -0,0 +1,76 @@ + + + + HSPA+ + DCHSPAP + Ekrano delsimas po: %1$d %2$s + GPS + GPS išjungta + Užmigti + Garsas įjungtas + Garsas išjungtas + Vibracija įjungta + Vibracija išjungta + Įjungti + Išjungti + Garsas + Užrakinti ekraną + Tinklo režimas + Išjungta + Įjungta + Pranešti apie klaidą + Sinchronizuoti + Sinchronizavimas išjungtas + Žibintuvėlis + Žibintuvėlis išjungtas + NFC + NFC išjungtas + Ekrano delsimo laikas + Atjungtas + Pririšimas išjungtas + Pririšimas + Profilis + Wi-Fi AP + Wi-Fi AP išjungtas + Tylos laikas + Tylos laikas išjungtas + LTE + LTE išjungtas + Garsas + Kamera + Pasirinkite veiksmą norėdami jį priskirti + Pagrindinis mygtukas + \'Naujų\' mygtukas + Paieškos mygtukas + Mygtukas atgal + Tuščias mygtukas + Meniu mygtukas (automatiškai slepiamas) + Meniu mygtukas (visada rodomas) + Meniu mygtukas + Įkraunama (%d%%) + Įkrauta + %d%% Likę + Nėra ryšio + Lėktuvo režimas įjungtas + Tik pagalbos skambučiai + Išplėstas + Normalus + Nepavyksta prisijungti prie kameros + Garsas %s. + Vibracija %s. + Naudoti Cido atvaizdą + Naudokite Cido atvaizdą vietoi Dražės svajonėje + From cfaedc81b2d301530b971db4c295d09d8c9834d3 Mon Sep 17 00:00:00 2001 From: Danny Baumann Date: Tue, 3 Dec 2013 14:35:56 +0100 Subject: [PATCH 185/204] Fix navbar editor for RTL layouts. Remove navigation bar layout XML override which wasn't needed anyway, as the views in mid_navigation_bar are already reordered based on the layout direction anyway. Change-Id: Id57c781d9580fa0cb2eab3bb332daf4136bec321 JIRA:CYAN-2557 --- .../res/layout-ldrtl/navigation_bar.xml | 322 ------------------ .../SystemUI/res/layout/navigation_bar.xml | 2 +- 2 files changed, 1 insertion(+), 323 deletions(-) delete mode 100644 packages/SystemUI/res/layout-ldrtl/navigation_bar.xml diff --git a/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml b/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml deleted file mode 100644 index 03ca729a72d42..0000000000000 --- a/packages/SystemUI/res/layout-ldrtl/navigation_bar.xml +++ /dev/null @@ -1,322 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml index 4511ea11e7339..e05cf86f8a4c5 100644 --- a/packages/SystemUI/res/layout/navigation_bar.xml +++ b/packages/SystemUI/res/layout/navigation_bar.xml @@ -39,7 +39,7 @@ android:clipToPadding="false" android:id="@+id/container" > - + From e35631781ae1bfdfd0c4e81a224590d3a2318760 Mon Sep 17 00:00:00 2001 From: oubeichen Date: Fri, 15 Nov 2013 13:44:43 +0800 Subject: [PATCH 186/204] Fix a bootloop problem when /data/system/usagestats/usage-history.xml is empty. This often occurs after an incomplete reboot/shutdown or battery pull. Change-Id: I4f01151f4051df4ae1b85fa460ec7a9e70122878 --- services/java/com/android/server/am/UsageStatsService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java index 6dae4aa1754cf..dcdf966bdd7bc 100644 --- a/services/java/com/android/server/am/UsageStatsService.java +++ b/services/java/com/android/server/am/UsageStatsService.java @@ -366,7 +366,7 @@ private void readHistoryStatsFLOCK(AtomicFile file) { XmlPullParser parser = Xml.newPullParser(); parser.setInput(fis, null); int eventType = parser.getEventType(); - while (eventType != XmlPullParser.START_TAG) { + while (eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_DOCUMENT) { eventType = parser.next(); } String tagName = parser.getName(); From 6909f215b454322f38d6c273d52765057c93161a Mon Sep 17 00:00:00 2001 From: Ethan Chen Date: Fri, 6 Dec 2013 00:33:37 -0800 Subject: [PATCH 187/204] Fix showing owner info creation from UserTile if no owner is set * Turns out the default user will always be present, meaning a check of user count == 0 fails. Change-Id: Id8e8e75c5f51c73a60d7b9039298ecb90e572bc9 --- .../systemui/quicksettings/UserTile.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java b/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java index ece5a8766c153..407a307ba8a9e 100644 --- a/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java +++ b/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java @@ -46,13 +46,18 @@ public void onClick(View v) { final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); int numUsers = um.getUsers(true).size(); - if (numUsers == 0) { - Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI); - intent.putExtra(INTENT_EXTRA_NEW_LOCAL_PROFILE, true); - startSettingsActivity(intent); - } else if (numUsers == 1) { - Intent intent = new Intent(Intent.ACTION_VIEW, ContactsContract.Profile.CONTENT_URI); - startSettingsActivity(intent); + if (numUsers <= 1) { + final Cursor cursor = mContext.getContentResolver().query( + Profile.CONTENT_URI, null, null, null, null); + if (cursor.moveToNext() && !cursor.isNull(0)) { + Intent intent = new Intent(Intent.ACTION_VIEW, ContactsContract.Profile.CONTENT_URI); + startSettingsActivity(intent); + } else { + Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI); + intent.putExtra(INTENT_EXTRA_NEW_LOCAL_PROFILE, true); + startSettingsActivity(intent); + } + cursor.close(); } else { try { WindowManagerGlobal.getWindowManagerService().lockNow( From e5b947e16545e300473b173ff7968c4a0b250777 Mon Sep 17 00:00:00 2001 From: Marco Brohet Date: Fri, 6 Dec 2013 19:35:58 +0100 Subject: [PATCH 188/204] core: add AST support Change-Id: I42203d7c0173e6cd880da3937f88e8f5c501db9d --- .../values-ast-rES/donottranslate-maps.xml | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 core/res/res/values-ast-rES/donottranslate-maps.xml diff --git a/core/res/res/values-ast-rES/donottranslate-maps.xml b/core/res/res/values-ast-rES/donottranslate-maps.xml new file mode 100644 index 0000000000000..4fc20a57c325b --- /dev/null +++ b/core/res/res/values-ast-rES/donottranslate-maps.xml @@ -0,0 +1,25 @@ + + + + + 5884131 + 2570560 + + + 4 + + From aeb8b53a30de67651a339fbca9a2f1750257c2e2 Mon Sep 17 00:00:00 2001 From: Marco Brohet Date: Sat, 7 Dec 2013 00:17:01 +0000 Subject: [PATCH 189/204] Revert "core: add AST support" This reverts commit e5b947e16545e300473b173ff7968c4a0b250777. Change-Id: If8fea813b1fdfc05be81e1e3a0213c85f3c35ecc --- .../values-ast-rES/donottranslate-maps.xml | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 core/res/res/values-ast-rES/donottranslate-maps.xml diff --git a/core/res/res/values-ast-rES/donottranslate-maps.xml b/core/res/res/values-ast-rES/donottranslate-maps.xml deleted file mode 100644 index 4fc20a57c325b..0000000000000 --- a/core/res/res/values-ast-rES/donottranslate-maps.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - 5884131 - 2570560 - - - 4 - - From d034bb8a0a25da4376bb65057308332bbcc7b8a6 Mon Sep 17 00:00:00 2001 From: Ethan Chen Date: Fri, 6 Dec 2013 18:25:28 -0800 Subject: [PATCH 190/204] Show default profile name if no profile exists Change-Id: I6b651d6b552ab3caf30102d289469eaf68f58a0e --- .../systemui/quicksettings/UserTile.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java b/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java index 407a307ba8a9e..327dc6eaf6ffd 100644 --- a/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java +++ b/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java @@ -15,6 +15,7 @@ import android.os.UserManager; import android.provider.ContactsContract; import android.provider.ContactsContract.Contacts; +import android.provider.ContactsContract.RawContacts; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.Profile; import android.util.Log; @@ -125,24 +126,15 @@ protected Pair doInBackground(Void... params) { final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - // Fall back to the UserManager nickname if we can't read the name from the local - // profile below. - String name = userName; + String name = null; Drawable avatar = null; - Bitmap rawAvatar = um.getUserIcon(userId); - if (rawAvatar != null) { - avatar = new BitmapDrawable(mContext.getResources(), rawAvatar); - } else { - avatar = mContext.getResources().getDrawable(R.drawable.ic_qs_default_user); - } - // If it's a single-user device, get the profile name, since the nickname is not // usually valid if (um.getUsers().size() <= 1) { // Try and read the display name from the local profile final Cursor cursor = context.getContentResolver().query( - Profile.CONTENT_URI, new String[] {Phone._ID, Phone.DISPLAY_NAME}, - null, null, null); + Profile.CONTENT_RAW_CONTACTS_URI, new String[] {Phone._ID, Phone.DISPLAY_NAME}, + RawContacts.DELETED + "=0", null, null); if (cursor != null) { try { if (cursor.moveToFirst()) { @@ -151,6 +143,19 @@ protected Pair doInBackground(Void... params) { } finally { cursor.close(); } + // Fall back to the UserManager nickname if we can't read the name from the local + // profile below. + if (name == null) { + avatar = mContext.getResources().getDrawable(R.drawable.ic_qs_default_user); + name = mContext.getResources().getString(com.android.internal.R.string.owner_name); + } else { + Bitmap rawAvatar = um.getUserIcon(userId); + if (rawAvatar != null) { + avatar = new BitmapDrawable(mContext.getResources(), rawAvatar); + } else { + avatar = mContext.getResources().getDrawable(R.drawable.ic_qs_default_user); + } + } } } return new Pair(name, avatar); From 995a2b3042ce00a448f318c2307bcef9285477b7 Mon Sep 17 00:00:00 2001 From: Danesh Mondegarian Date: Sun, 8 Dec 2013 20:50:54 -0800 Subject: [PATCH 191/204] UserTile : Check if profile has a photo In the event that the profile doesn't have a photo, don't default to the user's photo, instead show a default avatar. Change-Id: I80de324ae1e151693cf3716bf87d39a16096ca12 --- .../systemui/quicksettings/UserTile.java | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java b/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java index 327dc6eaf6ffd..30bd44f787bec 100644 --- a/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java +++ b/packages/SystemUI/src/com/android/systemui/quicksettings/UserTile.java @@ -1,5 +1,9 @@ package com.android.systemui.quicksettings; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + import android.app.ActivityManagerNative; import android.content.Context; import android.content.Intent; @@ -7,8 +11,10 @@ import android.content.pm.UserInfo; import android.database.Cursor; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.AsyncTask; import android.os.RemoteException; import android.os.UserHandle; @@ -128,17 +134,19 @@ protected Pair doInBackground(Void... params) { String name = null; Drawable avatar = null; + String id = null; // If it's a single-user device, get the profile name, since the nickname is not // usually valid if (um.getUsers().size() <= 1) { // Try and read the display name from the local profile final Cursor cursor = context.getContentResolver().query( - Profile.CONTENT_RAW_CONTACTS_URI, new String[] {Phone._ID, Phone.DISPLAY_NAME}, - RawContacts.DELETED + "=0", null, null); + Profile.CONTENT_URI, new String[] {Phone._ID, Phone.DISPLAY_NAME}, + null, null, null); if (cursor != null) { try { if (cursor.moveToFirst()) { name = cursor.getString(cursor.getColumnIndex(Phone.DISPLAY_NAME)); + id = cursor.getString(cursor.getColumnIndex(Phone._ID)); } } finally { cursor.close(); @@ -149,11 +157,24 @@ protected Pair doInBackground(Void... params) { avatar = mContext.getResources().getDrawable(R.drawable.ic_qs_default_user); name = mContext.getResources().getString(com.android.internal.R.string.owner_name); } else { - Bitmap rawAvatar = um.getUserIcon(userId); - if (rawAvatar != null) { + Bitmap rawAvatar = null; + InputStream is = null; + try { + Uri.Builder uriBuilder = ContactsContract.RawContacts.CONTENT_URI.buildUpon(); + uriBuilder.appendPath(id); + uriBuilder.appendPath(Contacts.Photo.DISPLAY_PHOTO); + is = mContext.getContentResolver().openInputStream(uriBuilder.build()); + rawAvatar = BitmapFactory.decodeStream(is); avatar = new BitmapDrawable(mContext.getResources(), rawAvatar); - } else { + } catch (FileNotFoundException e) { avatar = mContext.getResources().getDrawable(R.drawable.ic_qs_default_user); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + } + } } } } From 5a2e9ff0e4a434dc442c17b07e7e54c6b88d6e99 Mon Sep 17 00:00:00 2001 From: Qaweck Date: Fri, 6 Dec 2013 15:21:28 +0100 Subject: [PATCH 192/204] Fix bluetooth and data enable with ProfileManager Handle the case of system uid in AppOpsManager Change-Id: I5f9c3ba2e2ed0b1c825b995bf2724066ae796bb4 --- services/java/com/android/server/AppOpsService.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/services/java/com/android/server/AppOpsService.java b/services/java/com/android/server/AppOpsService.java index 284a5475016b5..50e4b5a788db1 100644 --- a/services/java/com/android/server/AppOpsService.java +++ b/services/java/com/android/server/AppOpsService.java @@ -219,12 +219,14 @@ public void systemReady() { Iterator it = pkgs.values().iterator(); while (it.hasNext()) { Ops ops = it.next(); - int curUid; + int curUid = -1; try { curUid = mContext.getPackageManager().getPackageUid(ops.packageName, UserHandle.getUserId(ops.uid)); } catch (NameNotFoundException e) { - curUid = -1; + if ("android".equals(ops.packageName)) { + curUid = Process.SYSTEM_UID; + } } if (curUid != ops.uid) { Slog.i(TAG, "Pruning old package " + ops.packageName @@ -819,6 +821,8 @@ private Ops getOpsLocked(int uid, String packageName, boolean edit) { packageName = "root"; } else if (uid == Process.SHELL_UID) { packageName = "com.android.shell"; + } else if (uid == Process.SYSTEM_UID) { + packageName = "android"; } Ops ops = pkgOps.get(packageName); if (ops == null) { @@ -827,7 +831,7 @@ private Ops getOpsLocked(int uid, String packageName, boolean edit) { } // This is the first time we have seen this package name under this uid, // so let's make sure it is valid. - if (uid != 0) { + if (uid != 0 && uid != Process.SYSTEM_UID) { final long ident = Binder.clearCallingIdentity(); try { int pkgUid = -1; From ef86fc5431944dedbb8ded8839d493bccfeb1b7d Mon Sep 17 00:00:00 2001 From: Danesh Mondegarian Date: Sun, 8 Dec 2013 22:43:44 -0800 Subject: [PATCH 193/204] CircleBattery : Add RTL support Use paddingStart for rtl compatibility Change-Id: I6c61dfe460eb31c25013c68928935c54dc18baff --- packages/SystemUI/res/layout/status_bar.xml | 2 +- .../systemui/statusbar/policy/CircleBattery.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml index 171ee6dbcc2b2..2ceaf5fa79c35 100644 --- a/packages/SystemUI/res/layout/status_bar.xml +++ b/packages/SystemUI/res/layout/status_bar.xml @@ -160,7 +160,7 @@ android:layout_height="match_parent" android:singleLine="true" android:paddingStart="6dip" - android:gravity="center_vertical|left" + android:gravity="center_vertical|start" android:clickable="false" /> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CircleBattery.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CircleBattery.java index a4348767126e8..ddb34c1af32db 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CircleBattery.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CircleBattery.java @@ -207,7 +207,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { initSizeMeasureIconHeight(); } - setMeasuredDimension(mCircleSize + getPaddingLeft(), mCircleSize); + setMeasuredDimension(mCircleSize + getPaddingStart(), mCircleSize); } protected int getBatteryLevel() { @@ -310,14 +310,14 @@ private void initSizeBasedStuff() { mPaintGray.setStrokeWidth(strokeWidth / 3.5f); // calculate rectangle for drawArc calls - int pLeft = getPaddingLeft(); - mRectLeft = new RectF(pLeft + strokeWidth / 2.0f, 0 + strokeWidth / 2.0f, mCircleSize - - strokeWidth / 2.0f + pLeft, mCircleSize - strokeWidth / 2.0f); + int pLeft = getPaddingStart(); + mRectLeft = new RectF(pLeft/2 + strokeWidth / 2.0f, 0 + strokeWidth / 2.0f, mCircleSize + - strokeWidth / 2.0f + pLeft/2, mCircleSize - strokeWidth / 2.0f); // calculate Y position for text Rect bounds = new Rect(); mPaintFont.getTextBounds("99", 0, "99".length(), bounds); - mTextLeftX = mCircleSize / 2.0f + getPaddingLeft(); + mTextLeftX = mCircleSize / 2.0f + getPaddingStart(); // the +1 at end of formular balances out rounding issues. works out on all resolutions mTextY = mCircleSize / 2.0f + (bounds.bottom - bounds.top) / 2.0f - strokeWidth / 2.0f + 1; From a396485fcbebdb57fb39abe66cce5bb68f19bd2b Mon Sep 17 00:00:00 2001 From: Ethan Chen Date: Mon, 9 Dec 2013 01:29:23 -0800 Subject: [PATCH 194/204] Add RTL variants for HSPAP H+ icon Change-Id: I281083572d07773e4a00079bd947bfd0f4ddf6bb --- .../stat_sys_data_connected_hp.png | Bin 0 -> 387 bytes .../stat_sys_data_connected_hp.png | Bin 0 -> 282 bytes .../stat_sys_data_connected_hp.png | Bin 0 -> 508 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_connected_hp.png create mode 100644 packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_connected_hp.png create mode 100644 packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_connected_hp.png diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_connected_hp.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_data_connected_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..cb6c1216b57d84d9d6665fdcce6260f782d260c8 GIT binary patch literal 387 zcmV-}0et?6P)FNpss@dqBST$za+S+D>A002ovPDHLkV1k?Ks4D;f literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_connected_hp.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_data_connected_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..583543443543c0d26538e9c6ccee2f5c74901086 GIT binary patch literal 282 zcmV+#0p!tg&$&`D1k0 z&AoG+=6co&jFEpsKRSEG$0}$7c3lUH^nKRd;}Hkh1dTIXvz3S|JmCV1Neb62QsoV< zu^bEA1US#S?TmNEoM`=rrIawd@*ehaXPDg~-tmBF21dlsNfQ-**BGw&nejZ8_mhCF gw#lRX1OFQE3l?cKM?q;07ytkO07*qoM6N<$f@0HiW&i*H literal 0 HcmV?d00001 diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_connected_hp.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_data_connected_hp.png new file mode 100644 index 0000000000000000000000000000000000000000..4852b923d2dc6d15a6f762f6248591a72333a380 GIT binary patch literal 508 zcmVjn4TBEgAfRbsewYD-p z)i)Rn0O&>`8<&+fudflfO<)_yfp_4OB3c&M0Cs?m_&$~fXN>WOE&?u19cyi7j5z_$ zfeg3+9t0)@j)5x~UjsKlB7Y=mk+hDGNC2tU8UV4W?-ToX z1{Z~^JIwx^tHxx;n#5b{+lfuF)e+mRjBB-MZU|;5IgVe;C zbIO53X}(fc04@Pufj7n@cQ9?kLU8Vx5&0>`7=u#ERi%Tw2kw9#@C}>-w^85%G@?l3 z7saKV&RX1bwI-BTOWhSSu{gFYMKR<+uC=zv7l=2XQC9oXF5&;EM;U~5vC11y^F@Vo z&(fpV5ipc~CUyv13fNO+Un6kO(&~IK(tI_V)`T*3{@H>eh3*M+=dX0e`b=Mjn!ZZr yQVSQV7A{mRT&P;OP_=NOYT-iF!i8$3;eG+9{dXwmVf7~f0000 Date: Mon, 9 Dec 2013 11:44:59 -0800 Subject: [PATCH 195/204] CircleBattery : Fix alignment regression from RTL Rather than distributing the padding evenly to get around RTL issues, remeasure on layout changes. Change-Id: Ic6f7a58bd64bf2c99f0e07edb0d8fb8cdb9aa398 --- .../systemui/statusbar/policy/CircleBattery.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CircleBattery.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CircleBattery.java index ddb34c1af32db..77523bd2b0168 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CircleBattery.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CircleBattery.java @@ -16,7 +16,6 @@ package com.android.systemui.statusbar.policy; -import android.view.ViewGroup.LayoutParams; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; @@ -292,6 +291,12 @@ private void updateChargeAnim() { mHandler.postDelayed(mInvalidate, 50); } + @Override + public void onRtlPropertiesChanged(int layoutDirection) { + mRectLeft = null; + invalidate(); + } + /** * initializes all size dependent variables * sets stroke width and text size of all involved paints @@ -311,13 +316,13 @@ private void initSizeBasedStuff() { // calculate rectangle for drawArc calls int pLeft = getPaddingStart(); - mRectLeft = new RectF(pLeft/2 + strokeWidth / 2.0f, 0 + strokeWidth / 2.0f, mCircleSize - - strokeWidth / 2.0f + pLeft/2, mCircleSize - strokeWidth / 2.0f); + mRectLeft = new RectF(getPaddingLeft() + strokeWidth / 2.0f, 0 + strokeWidth / 2.0f, mCircleSize + - strokeWidth / 2.0f + getPaddingLeft(), mCircleSize - strokeWidth / 2.0f); // calculate Y position for text Rect bounds = new Rect(); mPaintFont.getTextBounds("99", 0, "99".length(), bounds); - mTextLeftX = mCircleSize / 2.0f + getPaddingStart(); + mTextLeftX = mCircleSize / 2.0f + pLeft; // the +1 at end of formular balances out rounding issues. works out on all resolutions mTextY = mCircleSize / 2.0f + (bounds.bottom - bounds.top) / 2.0f - strokeWidth / 2.0f + 1; From 2d7344dc1f6789b36843e73ee9b5aac430d948a2 Mon Sep 17 00:00:00 2001 From: Danesh M Date: Wed, 11 Dec 2013 10:46:11 -0800 Subject: [PATCH 196/204] CircleBattery : Use consistent padding for layoutDirection Use padding left consitently since paddingStart takes care of its automatic value. Change-Id: I187e79489a26dd4e5328f816bb69c79f177697e8 --- .../android/systemui/statusbar/policy/CircleBattery.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CircleBattery.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CircleBattery.java index 77523bd2b0168..50dd38fe117ad 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CircleBattery.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CircleBattery.java @@ -315,9 +315,9 @@ private void initSizeBasedStuff() { mPaintGray.setStrokeWidth(strokeWidth / 3.5f); // calculate rectangle for drawArc calls - int pLeft = getPaddingStart(); - mRectLeft = new RectF(getPaddingLeft() + strokeWidth / 2.0f, 0 + strokeWidth / 2.0f, mCircleSize - - strokeWidth / 2.0f + getPaddingLeft(), mCircleSize - strokeWidth / 2.0f); + int pLeft = getPaddingLeft(); + mRectLeft = new RectF(pLeft + strokeWidth / 2.0f, 0 + strokeWidth / 2.0f, mCircleSize + - strokeWidth / 2.0f + pLeft, mCircleSize - strokeWidth / 2.0f); // calculate Y position for text Rect bounds = new Rect(); From bfe1d69201d444d3c76c4a9bc325e4b58135bd7b Mon Sep 17 00:00:00 2001 From: Frant1c Date: Sat, 14 Dec 2013 08:26:00 +0200 Subject: [PATCH 197/204] Frameworks: LT translations Small fixes Change-Id: I0b766d6950083d08783cf7aeb57445f6d8322e77 --- core/res/res/values-lt/cm_strings.xml | 10 +++++----- core/res/res/values-lt/strings.xml | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/res/res/values-lt/cm_strings.xml b/core/res/res/values-lt/cm_strings.xml index 6b98d2928d4b8..89f7c8016f4a3 100644 --- a/core/res/res/values-lt/cm_strings.xml +++ b/core/res/res/values-lt/cm_strings.xml @@ -27,9 +27,9 @@ Perkrauti planšetinį kompiuterį Perkrauti telefoną Ekranvaizdis - Išplėstas darbalaukis - Įjungta - Išjungta + Išplėstas darbastalis + Įjungtas + Išjungtas Perkrauti Atkūrimo režimas \'Bootloader\' @@ -79,7 +79,7 @@ PIN operacija nepavyko! PUK operacija nepavyko! Kodas priimtas! - \nLikę bandymai : + \nLikę bandymai: Negaliojanti kortelė. Negaliojanti SIM kortelė. SIM/RUIM kortelė yra užrakinta. @@ -89,6 +89,6 @@ SS užklausa pakeista į naują DIAL prašymą. SS užklausa pakeista į naują USSD prašymą. SS užklausa pakeista į naują. - SUB:%d : %s. + PREN.:%d : %s. %s, %s diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 593316f2fe292..171363f0b6217 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -158,11 +158,11 @@ "Pranešti apie triktį" "Bus surinkta informacija apie dabartinę įrenginio būseną ir išsiųsta el. pašto pranešimu. Šiek tiek užtruks, kol pranešimas apie triktį bus paruoštas siųsti; būkite kantrūs." "Tylus režimas" - "Garsas IŠJUNGTAS" - "Garsas ĮJUNGTAS" + "Išjungtas" + "Įjungtas" "Lėktuvo režimas" - "ĮJUNGTAS lėktuvo režimas" - "lėktuvo režimas IŠJUNGTAS" + "Įjungtas" + "Išjungtas" "999+" "Saugos režimas" "„Android“ sistema" From b1684ede9efc0392243e9ade5b0832838c6b0e69 Mon Sep 17 00:00:00 2001 From: Tomasz Popielarczyk Date: Mon, 16 Dec 2013 23:39:26 +0100 Subject: [PATCH 198/204] SystemUI: PL translations Change-Id: I61cd2410aac3e0cf99023d00f82a8467d9f4bbec --- packages/SystemUI/res/values-pl/cm_strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/SystemUI/res/values-pl/cm_strings.xml b/packages/SystemUI/res/values-pl/cm_strings.xml index 65eae6774aba5..d1cdf6794b0a1 100644 --- a/packages/SystemUI/res/values-pl/cm_strings.xml +++ b/packages/SystemUI/res/values-pl/cm_strings.xml @@ -49,6 +49,8 @@ LTE wył. Głośność Kamera + ADB wył. + ADB Wybierz akcję do przypisania Przycisk Home Przycisk Ostatnie aplikacje From ab8ca41d2246d398b9f80709c49ea1e19b7061e0 Mon Sep 17 00:00:00 2001 From: Tomasz Popielarczyk Date: Tue, 17 Dec 2013 00:08:17 +0100 Subject: [PATCH 199/204] Core: PL translations Change-Id: I4440e5d749cb40581df13192b184aaff7fa806b1 --- core/res/res/values-pl/cm_arrays.xml | 55 +++++++++++++++++++++++++++ core/res/res/values-pl/cm_strings.xml | 20 ++++++++++ 2 files changed, 75 insertions(+) create mode 100644 core/res/res/values-pl/cm_arrays.xml diff --git a/core/res/res/values-pl/cm_arrays.xml b/core/res/res/values-pl/cm_arrays.xml new file mode 100644 index 0000000000000..fff2ad0936817 --- /dev/null +++ b/core/res/res/values-pl/cm_arrays.xml @@ -0,0 +1,55 @@ + + + + + + Podjęto próbę uzyskania dostępu do lokalizacji + Podjęto próbę uzyskania dostępu do lokalizacji + Podjęto próbę uzyskania dostępu do lokalizacji + Podjęto próbę użycia wibracji + Podjęto próbę odczytania kontaktów + Podjęto próbę zmodyfikowania kontaktów + Podjęto próbę odczytania rejestru połączeń + Podjęto próbę zmodyfikowania rejestru połączeń + Podjęto próbę odczytania kalendarza + Podjęto próbę zmodyfikowania kalendarza + Podjęto próbę uzyskania dostępu do lokalizacji + Podjęto próbę aktywowania powiadomienia + Podjęto próbę uzyskania dostępu do lokalizacji + Podjęto próbę wykonania połączenia głosowego + Podjęto próbę odczytania wiadomości SMS/MMS + Podjęto próbę pisania/edytowania wiadomości SMS/MMS + Podjęto próbę odebrania wiadomości SMS/MMS + Podjęto próbę odebrania wiadomości SMS/MMS + Podjęto próbę odebrania wiadomości SMS/MMS + Podjęto próbę odebrania wiadomości SMS/MMS + Podjęto próbę wysłania wiadomości SMS/MMS + Podjęto próbę odczytania wiadomości SMS/MMS + Podjęto próbę pisania/edytowania wiadomości SMS/MMS + Podjęto próbę modyfikowania ustawień + Podjęto próbę wysunięcia aplikacji na wierzch + Podjęto próbę uzyskania dostępu do powiadomień + Podjęto próbę uzyskania dostępu do kamery + Podjęto próbę nagrywania dźwięku + Podjęto próbę odtwarzania dźwięku + Podjęto próbę odczytania schowka + Podjęto próbę zmodyfikowania schowka + Podjęto próbę przełączenia stanu WiFi + Podjęto próbę przełączenia stanu Bluetooth + Podjęto próbę przełączenia stanu danych mobilnych + Podjęto próbę zaplanowania wybudzenia urządzenia + + diff --git a/core/res/res/values-pl/cm_strings.xml b/core/res/res/values-pl/cm_strings.xml index 8e937e177837b..bea908c2eadac 100644 --- a/core/res/res/values-pl/cm_strings.xml +++ b/core/res/res/values-pl/cm_strings.xml @@ -71,4 +71,24 @@ Przełącza między wymuszaniem polityki SELinux a trybem pobłażliwym. Wymuś MMAC Przełącza między wymuszaniem polityki MMAC a trybem pobłażliwym. + Oszczędzanie energii + Zrównoważony + Wydajność + Żądanie USSD jest modyfikowane na żądanie DIAL. + Żądanie USSD jest modyfikowane na żądanie SS. + Żądanie USSD jest modyfikowane na nowe żądanie USSD. + Żądanie SS jest modyfikowane na żądanie DIAL. + Żądanie SS jest modyfikowane na żądanie USSD. + Żądanie SS jest modyfikowane na nowe żądanie SS. + USŁUGA:%d : %s. + %s, %s + Niepoprawna karta. + Niepoprawna karta SIM. + Karta SIM/RUIM jest zablokowana + \nPozostałe próby: + Niepoprawny kod PUK! + Operacja PIN nie powiodła się! + Operacja PUK nie powiodła się! + Kod zaakceptowany! + Niepowodzenie. Włącz blokadę SIM/RUIM. From 2e1eb88081421dfc8c5aa4d31b71e1da2e166bbd Mon Sep 17 00:00:00 2001 From: FPtje Date: Fri, 27 Dec 2013 16:59:31 +0100 Subject: [PATCH 200/204] Fixed stylus eraser being rejected by palm rejection The stylus eraser appeared not to work, i.e. Android did not respond to input from the eraser. It turned out that all input except stylus input is rejected when palm rejection is activated. The problem was that the eraser itself activates palm rejection when it hovers. The solution is to allow the eraser during palm rejection. This solution makes sense because the eraser input works in the exact same way as normal stylus input. Change-Id: I90824500be7613af4f00427c59ce828528b632f7 --- services/input/InputReader.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp index 10dbaf42f64f1..622beecf9ff83 100644 --- a/services/input/InputReader.cpp +++ b/services/input/InputReader.cpp @@ -5717,7 +5717,8 @@ nsecs_t TouchInputMapper::mLastStylusTime = 0; bool TouchInputMapper::rejectPalm(nsecs_t when) { return (when - mLastStylusTime < mConfig.stylusPalmRejectionTime) && - mPointerSimple.currentProperties.toolType != AMOTION_EVENT_TOOL_TYPE_STYLUS; + mPointerSimple.currentProperties.toolType != AMOTION_EVENT_TOOL_TYPE_STYLUS && + mPointerSimple.currentProperties.toolType != AMOTION_EVENT_TOOL_TYPE_ERASER; } bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) { From 94b18342b1930cba26fdde8a15cb7a14a17a9e22 Mon Sep 17 00:00:00 2001 From: Marco Brohet Date: Sat, 28 Dec 2013 18:02:30 +0100 Subject: [PATCH 201/204] core: Add support for Asturian Change-Id: I01892a3743affd7449f0c87859ff7b151f630f1c (cherry picked from commit 4875495b005afb58392638599be54dd501939d6f) --- .../res/values-es-rXA/donottranslate-maps.xml | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 core/res/res/values-es-rXA/donottranslate-maps.xml diff --git a/core/res/res/values-es-rXA/donottranslate-maps.xml b/core/res/res/values-es-rXA/donottranslate-maps.xml new file mode 100644 index 0000000000000..2e49ced540f9b --- /dev/null +++ b/core/res/res/values-es-rXA/donottranslate-maps.xml @@ -0,0 +1,26 @@ + + + + + + 40413496 + -3713379 + + + 6 + + From e55224ba664c651a49d82ff955e9d12e54b7e628 Mon Sep 17 00:00:00 2001 From: Kyrylo Mikos Date: Tue, 17 Dec 2013 18:21:49 +0200 Subject: [PATCH 202/204] BluetoothManagerService: fix enabling/disabling BT from Quictsettings under second user, Change-Id: I8173559b2c734968ef4a8d86fddaa3a73d5c2b1e (cherry picked from commit fe625c56d15eb091caddbf115ef90ebdf62490c0) --- .../android/server/BluetoothManagerService.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java index 8cb1ed7af1146..1763a1810a34c 100644 --- a/services/java/com/android/server/BluetoothManagerService.java +++ b/services/java/com/android/server/BluetoothManagerService.java @@ -57,6 +57,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid"; private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address"; private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name"; + private static final String SYSTEMUI_PACKAGE_NAME="com.android.systemui"; private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save //Maximum msec to wait for service restart @@ -1110,11 +1111,20 @@ private boolean checkIfCallerIsForegroundUser() { int callingUid = Binder.getCallingUid(); long callingIdentity = Binder.clearCallingIdentity(); int callingAppId = UserHandle.getAppId(callingUid); + String[] packages = mContext.getPackageManager().getPackagesForUid(callingUid); + boolean isSystemUi = false; + for (String p : packages) { + if (SYSTEMUI_PACKAGE_NAME.equals(p)) { + isSystemUi = true; + break; + } + } boolean valid = false; try { foregroundUser = ActivityManager.getCurrentUser(); - valid = (callingUser == foregroundUser) || - callingAppId == Process.NFC_UID; + valid = (callingUser == foregroundUser) + || callingAppId == Process.NFC_UID + || isSystemUi; if (DBG) { Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid + " callingUser=" + callingUser From 3e306700643f4bff4578573852c43cbe9589b2cf Mon Sep 17 00:00:00 2001 From: Cristoforo Cataldo Date: Fri, 31 Jan 2014 07:36:29 +0100 Subject: [PATCH 203/204] GlobalActions: Set the initial status of airplane mode toggle Actually, the initial status of airplane mode toggle is set to false when the power menu dialog is initialized. This causes an issue if you set airplane mode and then reboot. After the reboot, the dialog displays the wrong airplane mode status, eg. "Airplane mode is not active", and if you toggle that option, a wrong intent is sent again to put ON the airplane mode, instead of OFF, the toggle (that is in transition state) will be set disabled. This commit fixes this issue. Change-Id: Id30355c1e090355645c437086c79ab59093c27a8 (cherry picked from commit 9b9df54cd2a24b3fce8f5e24052b3a348bef1995) --- .../internal/policy/impl/GlobalActions.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java index c77b31f48faf8..b0dfdf480f5b1 100644 --- a/policy/src/com/android/internal/policy/impl/GlobalActions.java +++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java @@ -159,6 +159,9 @@ public GlobalActions(Context context, WindowManagerFuncs windowManagerFuncs) { mShowSilentToggle = SHOW_SILENT_TOGGLE && !mContext.getResources().getBoolean( com.android.internal.R.bool.config_useFixedVolume); + + // set the initial status of airplane mode toggle + mAirplaneState = getUpdatedAirplaneToggleState(); } /** @@ -1209,15 +1212,17 @@ public void handleMessage(Message msg) { } }; + private ToggleAction.State getUpdatedAirplaneToggleState() { + return (Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 0) == 1) ? + ToggleAction.State.On : ToggleAction.State.Off; + } + private void onAirplaneModeChanged() { // Let the service state callbacks handle the state. if (mHasTelephony) return; - boolean airplaneModeOn = Settings.Global.getInt( - mContext.getContentResolver(), - Settings.Global.AIRPLANE_MODE_ON, - 0) == 1; - mAirplaneState = airplaneModeOn ? ToggleAction.State.On : ToggleAction.State.Off; + mAirplaneState = getUpdatedAirplaneToggleState(); mAirplaneModeOn.updateState(mAirplaneState); } From 677b2c0d07a53e90f108fce7264e2bdb63371211 Mon Sep 17 00:00:00 2001 From: Clyde Tan Date: Mon, 3 Mar 2014 20:32:08 +0800 Subject: [PATCH 204/204] Fix the screen-off animation ignoring value set in ro.sf.hwrotation Change-Id: I0afe5a6f5a1f17f92e615ef79fa6e52226c40522 --- .../android/server/power/ElectronBeam.java | 61 ++++++++++++++----- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/services/java/com/android/server/power/ElectronBeam.java b/services/java/com/android/server/power/ElectronBeam.java index 379e704ab1d9e..69fa83cbcca75 100644 --- a/services/java/com/android/server/power/ElectronBeam.java +++ b/services/java/com/android/server/power/ElectronBeam.java @@ -31,6 +31,7 @@ import android.opengl.GLES10; import android.opengl.GLES11Ext; import android.os.Looper; +import android.os.SystemProperties; import android.util.FloatMath; import android.util.Slog; import android.view.Display; @@ -90,6 +91,8 @@ final class ElectronBeam { private EGLSurface mEglSurface; private boolean mSurfaceVisible; private float mSurfaceAlpha; + private final int mHWRotation; + private final boolean mSwapNeeded; // Texture names. We only use one texture, which contains the screenshot. private final int[] mTexNames = new int[1]; @@ -119,6 +122,8 @@ final class ElectronBeam { public ElectronBeam(DisplayManagerService displayManager) { mDisplayManager = displayManager; + mHWRotation = Integer.parseInt(SystemProperties.get("ro.sf.hwrotation", "0")) / 90; + mSwapNeeded = mHWRotation % 2 == 1; } /** @@ -139,8 +144,14 @@ public boolean prepare(int mode) { // This is not expected to change while the electron beam surface is showing. DisplayInfo displayInfo = mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY); mDisplayLayerStack = displayInfo.layerStack; - mDisplayWidth = displayInfo.getNaturalWidth(); - mDisplayHeight = displayInfo.getNaturalHeight(); + + if (mSwapNeeded) { + mDisplayWidth = displayInfo.getNaturalHeight(); + mDisplayHeight = displayInfo.getNaturalWidth(); + } else { + mDisplayWidth = displayInfo.getNaturalWidth(); + mDisplayHeight = displayInfo.getNaturalHeight(); + } // Prepare the surface for drawing. if (!tryPrepare()) { @@ -287,17 +298,17 @@ private void drawVStretch(float stretch) { GLES10.glEnableClientState(GLES10.GL_TEXTURE_COORD_ARRAY); // draw the red plane - setVStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ar); + setVStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ar, mSwapNeeded); GLES10.glColorMask(true, false, false, true); GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4); // draw the green plane - setVStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ag); + setVStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ag, mSwapNeeded); GLES10.glColorMask(false, true, false, true); GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4); // draw the blue plane - setVStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ab); + setVStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ab, mSwapNeeded); GLES10.glColorMask(false, false, true, true); GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4); @@ -337,7 +348,7 @@ private void drawHStretch(float stretch) { GLES10.glEnableClientState(GLES10.GL_VERTEX_ARRAY); // draw narrow fading white line - setHStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ag); + setHStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ag, mSwapNeeded); GLES10.glColor4f(1.0f - ag, 1.0f - ag, 1.0f - ag, 1.0f); GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4); @@ -346,17 +357,33 @@ private void drawHStretch(float stretch) { } } - private static void setVStretchQuad(FloatBuffer vtx, float dw, float dh, float a) { - final float w = dw + (dw * a); - final float h = dh - (dh * a); + private static void setVStretchQuad(FloatBuffer vtx, float dw, float dh, float a, + boolean swap) { + final float w; + final float h; + if (swap) { + w = dw - (dw * a); + h = dh + (dh * a); + } else { + w = dw + (dw * a); + h = dh - (dh * a); + } final float x = (dw - w) * 0.5f; final float y = (dh - h) * 0.5f; setQuad(vtx, x, y, w, h); } - private static void setHStretchQuad(FloatBuffer vtx, float dw, float dh, float a) { - final float w = dw + (dw * a); - final float h = 1.0f; + private static void setHStretchQuad(FloatBuffer vtx, float dw, float dh, float a, + boolean swap) { + final float w; + final float h; + if (swap) { + w = 1.0f; + h = dh + (dh * a); + } else { + w = dw + (dw * a); + h = 1.0f; + } final float x = (dw - w) * 0.5f; final float y = (dh - h) * 0.5f; setQuad(vtx, x, y, w, h); @@ -526,7 +553,8 @@ private boolean createSurface() { mSurface = new Surface(); mSurface.copyFrom(mSurfaceControl); - mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManager, mSurfaceControl); + mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManager, mSurfaceControl, + mHWRotation); mSurfaceLayout.onDisplayTransaction(); } finally { SurfaceControl.closeTransaction(); @@ -686,11 +714,14 @@ public void dump(PrintWriter pw) { private static final class NaturalSurfaceLayout implements DisplayTransactionListener { private final DisplayManagerService mDisplayManager; private SurfaceControl mSurfaceControl; + private final int mHWRotation; - public NaturalSurfaceLayout(DisplayManagerService displayManager, SurfaceControl surfaceControl) { + public NaturalSurfaceLayout(DisplayManagerService displayManager, + SurfaceControl surfaceControl, int hwRotation) { mDisplayManager = displayManager; mSurfaceControl = surfaceControl; mDisplayManager.registerDisplayTransactionListener(this); + mHWRotation = hwRotation; } public void dispose() { @@ -708,7 +739,7 @@ public void onDisplayTransaction() { } DisplayInfo displayInfo = mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY); - switch (displayInfo.rotation) { + switch ((displayInfo.rotation + mHWRotation) % 4) { case Surface.ROTATION_0: mSurfaceControl.setPosition(0, 0); mSurfaceControl.setMatrix(1, 0, 0, 1);