diff options
author | Selim Cinek <cinek@google.com> | 2016-09-23 22:00:42 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2016-09-23 22:00:42 +0000 |
commit | 0e1f78da65eb57f249e00a6af4d6ad9298cca803 (patch) | |
tree | e18e55f15f1784500a3e2ea7bdc3f8bb5afb89e1 | |
parent | 21f25acb1011e2b00282b8eb1173529b8391364b (diff) | |
parent | 705442fa7dcbf1bf92595fdaca6cc888810931d8 (diff) |
Added Emergency affordance feature
am: 705442fa7d
Change-Id: I03ebb84119f9cb310882ba9ea90ee1e1d7118d03
-rwxr-xr-x | core/java/android/provider/Settings.java | 8 | ||||
-rw-r--r-- | core/java/com/android/internal/policy/EmergencyAffordanceManager.java | 101 | ||||
-rw-r--r-- | core/res/res/drawable/emergency_icon.xml | 40 | ||||
-rw-r--r-- | core/res/res/values/config.xml | 10 | ||||
-rw-r--r-- | core/res/res/values/strings.xml | 3 | ||||
-rw-r--r-- | core/res/res/values/symbols.xml | 6 | ||||
-rw-r--r-- | packages/Keyguard/src/com/android/keyguard/EmergencyButton.java | 43 | ||||
-rw-r--r-- | services/core/java/com/android/server/emergency/EmergencyAffordanceService.java | 312 | ||||
-rw-r--r-- | services/core/java/com/android/server/policy/GlobalActions.java | 29 | ||||
-rw-r--r-- | services/java/com/android/server/SystemServer.java | 9 |
10 files changed, 557 insertions, 4 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index e91af140581b..ed4675f57712 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -44,7 +44,6 @@ import android.net.ConnectivityManager; import android.net.Uri; import android.net.wifi.WifiManager; import android.os.BatteryManager; -import android.os.Binder; import android.os.Bundle; import android.os.DropBoxManager; import android.os.IBinder; @@ -8372,6 +8371,13 @@ public final class Settings { public static final String CALL_AUTO_RETRY = "call_auto_retry"; /** + * A setting that can be read whether the emergency affordance is currently needed. + * The value is a boolean (1 or 0). + * @hide + */ + public static final String EMERGENCY_AFFORDANCE_NEEDED = "emergency_affordance_needed"; + + /** * See RIL_PreferredNetworkType in ril.h * @hide */ diff --git a/core/java/com/android/internal/policy/EmergencyAffordanceManager.java b/core/java/com/android/internal/policy/EmergencyAffordanceManager.java new file mode 100644 index 000000000000..bed7c1ba4ed3 --- /dev/null +++ b/core/java/com/android/internal/policy/EmergencyAffordanceManager.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.internal.policy; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.provider.Settings; + +/** + * A class that manages emergency affordances and enables immediate calling to emergency services + */ +public class EmergencyAffordanceManager { + + public static final boolean ENABLED = true; + + /** + * Global setting override with the number to call with the emergency affordance. + * @hide + */ + private static final String EMERGENCY_CALL_NUMBER_SETTING = "emergency_affordance_number"; + + /** + * Global setting, whether the emergency affordance should be shown regardless of device state. + * The value is a boolean (1 or 0). + * @hide + */ + private static final String FORCE_EMERGENCY_AFFORDANCE_SETTING = "force_emergency_affordance"; + + private final Context mContext; + + public EmergencyAffordanceManager(Context context) { + mContext = context; + } + + /** + * perform an emergency call. + */ + public final void performEmergencyCall() { + performEmergencyCall(mContext); + } + + private static Uri getPhoneUri(Context context) { + String number = context.getResources().getString( + com.android.internal.R.string.config_emergency_call_number); + if (Build.IS_DEBUGGABLE) { + String override = Settings.Global.getString( + context.getContentResolver(), EMERGENCY_CALL_NUMBER_SETTING); + if (override != null) { + number = override; + } + } + return Uri.fromParts("tel", number, null); + } + + private static void performEmergencyCall(Context context) { + Intent intent = new Intent(Intent.ACTION_CALL_EMERGENCY); + intent.setData(getPhoneUri(context)); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + + /** + * @return whether emergency affordance should be active. + */ + public boolean needsEmergencyAffordance() { + if (!ENABLED) { + return false; + } + if (forceShowing()) { + return true; + } + return isEmergencyAffordanceNeeded(); + } + + private boolean isEmergencyAffordanceNeeded() { + return Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.EMERGENCY_AFFORDANCE_NEEDED, 0) != 0; + } + + + private boolean forceShowing() { + return Settings.Global.getInt(mContext.getContentResolver(), + FORCE_EMERGENCY_AFFORDANCE_SETTING, 0) != 0; + } +} diff --git a/core/res/res/drawable/emergency_icon.xml b/core/res/res/drawable/emergency_icon.xml new file mode 100644 index 000000000000..b2ffa2b4481c --- /dev/null +++ b/core/res/res/drawable/emergency_icon.xml @@ -0,0 +1,40 @@ +<!-- +Copyright (C) 2014 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24.0dp" + android:height="24.0dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="#FF000000" + android:pathData="M6.8,17.3C5.3,15.9 4.5,14.0 4.5,12.0c0.0,-2.0 0.8,-3.8 2.1,-5.2l1.4,1.4c-1.0,1.0 -1.6,2.4 -1.6,3.8c0.0,1.5 0.6,2.9 1.6,3.9L6.8,17.3z"/> + <path + android:fillColor="#FF000000" + android:pathData="M3.3,20.2C1.2,18.0 0.0,15.1 0.0,12.0c0.0,-3.1 1.2,-6.0 3.3,-8.2l1.4,1.4C3.0,7.0 2.0,9.4 2.0,12.0s1.0,5.0 2.7,6.9L3.3,20.2z"/> + <path + android:fillColor="#FF000000" + android:pathData="M17.2,17.3l-1.4,-1.4c1.1,-1.0 1.6,-2.4 1.6,-3.9c0.0,-1.4 -0.6,-2.8 -1.6,-3.8l1.4,-1.4c1.4,1.4 2.1,3.3 2.1,5.2C19.5,14.0 18.7,15.9 17.2,17.3z"/> + <path + android:fillColor="#FF000000" + android:pathData="M20.7,20.2l-1.4,-1.4C21.0,17.0 22.0,14.6 22.0,12.0c0.0,-2.6 -1.0,-5.0 -2.7,-6.9l1.4,-1.4C22.8,6.0 24.0,8.9 24.0,12.0C24.0,15.1 22.8,18.0 20.7,20.2z"/> + <path + android:fillColor="#FF000000" + android:pathData="M11.0,15.0l2.0,0.0l0.0,2.0l-2.0,0.0z"/> + <path + android:fillColor="#FF000000" + android:pathData="M11.0,7.0l2.0,0.0l0.0,6.0l-2.0,0.0z"/> +</vector> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 43f8dc769432..8a77fc94a48a 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2573,6 +2573,16 @@ <!-- True if the device supports system navigation keys. --> <bool name="config_supportSystemNavigationKeys">false</bool> + <!-- emergency call number for the emergency affordance --> + <string name="config_emergency_call_number" translatable="false">112</string> + + <!-- Do not translate. Mcc codes whose existence trigger the presence of emergency + affordances--> + <integer-array name="config_emergency_mcc_codes" translatable="false"> + <item>404</item> + <item>405</item> + </integer-array> + <!-- Package name for the device provisioning package. --> <string name="config_deviceProvisioningPackage"></string> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index bbcd6d57f30a..4080bb774a47 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -486,6 +486,9 @@ <!-- TODO: promote to separate string--> <string name="global_action_restart" translatable="false">@string/sim_restart_button</string> + <!-- label for item that starts emergency call --> + <string name="global_action_emergency">Emergency</string> + <!-- label for item that generates a bug report in the phone options dialog --> <string name="global_action_bug_report">Bug report</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index f02b9d0db646..7f093827204b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2673,6 +2673,10 @@ <java-symbol type="string" name="lockscreen_storage_locked" /> + <java-symbol type="string" name="global_action_emergency" /> + <java-symbol type="string" name="config_emergency_call_number" /> + <java-symbol type="array" name="config_emergency_mcc_codes" /> + <!-- Used for MimeIconUtils. --> <java-symbol type="drawable" name="ic_doc_apk" /> <java-symbol type="drawable" name="ic_doc_audio" /> @@ -2709,6 +2713,8 @@ <java-symbol type="drawable" name="ic_restart" /> + <java-symbol type="drawable" name="emergency_icon" /> + <java-symbol type="array" name="config_convert_to_emergency_number_map" /> <java-symbol type="array" name="config_nonBlockableNotificationPackages" /> diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java index 8d411453b5ae..0474df7bd89c 100644 --- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java +++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java @@ -28,13 +28,16 @@ import android.os.UserHandle; import android.telecom.TelecomManager; import android.util.AttributeSet; import android.util.Slog; +import android.view.MotionEvent; import android.view.View; +import android.view.ViewConfiguration; import android.widget.Button; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.internal.telephony.IccCardConstants.State; import com.android.internal.widget.LockPatternUtils; +import com.android.internal.policy.EmergencyAffordanceManager; /** * This class implements a smart emergency button that updates itself based @@ -51,7 +54,10 @@ public class EmergencyButton extends Button { | Intent.FLAG_ACTIVITY_CLEAR_TOP); private static final String LOG_TAG = "EmergencyButton"; + private final EmergencyAffordanceManager mEmergencyAffordanceManager; + private int mDownX; + private int mDownY; KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() { @Override @@ -64,6 +70,7 @@ public class EmergencyButton extends Button { updateEmergencyCallButton(); } }; + private boolean mLongPressWasDragged; public interface EmergencyButtonCallback { public void onEmergencyButtonClickedWhenInCall(); @@ -86,6 +93,7 @@ public class EmergencyButton extends Button { com.android.internal.R.bool.config_voice_capable); mEnableEmergencyCallWhileSimLocked = mContext.getResources().getBoolean( com.android.internal.R.bool.config_enable_emergency_call_while_sim_locked); + mEmergencyAffordanceManager = new EmergencyAffordanceManager(context); } @Override @@ -110,10 +118,45 @@ public class EmergencyButton extends Button { takeEmergencyCallAction(); } }); + setOnLongClickListener(new OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + if (!mLongPressWasDragged + && mEmergencyAffordanceManager.needsEmergencyAffordance()) { + mEmergencyAffordanceManager.performEmergencyCall(); + return true; + } + return false; + } + }); updateEmergencyCallButton(); } @Override + public boolean onTouchEvent(MotionEvent event) { + final int x = (int) event.getX(); + final int y = (int) event.getY(); + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { + mDownX = x; + mDownY = y; + mLongPressWasDragged = false; + } else { + final int xDiff = Math.abs(x - mDownX); + final int yDiff = Math.abs(y - mDownY); + int touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop(); + if (Math.abs(yDiff) > touchSlop || Math.abs(xDiff) > touchSlop) { + mLongPressWasDragged = true; + } + } + return super.onTouchEvent(event); + } + + @Override + public boolean performLongClick() { + return super.performLongClick(); + } + + @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); updateEmergencyCallButton(); diff --git a/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java new file mode 100644 index 000000000000..cca9f10c630b --- /dev/null +++ b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2016 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.emergency; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; +import android.provider.Settings; +import android.telephony.CellInfo; +import android.telephony.CellInfoGsm; +import android.telephony.CellInfoLte; +import android.telephony.CellInfoWcdma; +import android.telephony.CellLocation; +import android.telephony.PhoneStateListener; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import com.android.server.SystemService; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * A service that listens to connectivity and SIM card changes and determines if the emergency mode + * should be enabled + */ +public class EmergencyAffordanceService extends SystemService { + + private static final String TAG = "EmergencyAffordanceService"; + + private static final int NUM_SCANS_UNTIL_ABORT = 4; + + private static final int INITIALIZE_STATE = 1; + private static final int CELL_INFO_STATE_CHANGED = 2; + private static final int SUBSCRIPTION_CHANGED = 3; + + /** + * Global setting, whether the last scan of the sim cards reveal that a sim was inserted that + * requires the emergency affordance. The value is a boolean (1 or 0). + * @hide + */ + private static final String EMERGENCY_SIM_INSERTED_SETTING = "emergency_sim_inserted_before"; + + private final Context mContext; + private final ArrayList<Integer> mEmergencyCallMccNumbers; + + private final Object mLock = new Object(); + + private TelephonyManager mTelephonyManager; + private SubscriptionManager mSubscriptionManager; + private boolean mEmergencyAffordanceNeeded; + private MyHandler mHandler; + private int mScansCompleted; + private PhoneStateListener mPhoneStateListener = new PhoneStateListener() { + @Override + public void onCellInfoChanged(List<CellInfo> cellInfo) { + if (!isEmergencyAffordanceNeeded()) { + requestCellScan(); + } + } + + @Override + public void onCellLocationChanged(CellLocation location) { + if (!isEmergencyAffordanceNeeded()) { + requestCellScan(); + } + } + }; + private BroadcastReceiver mAirplaneModeReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (Settings.Global.getInt(context.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 0) == 0) { + startScanning(); + requestCellScan(); + } + } + }; + private boolean mSimNeedsEmergencyAffordance; + private boolean mNetworkNeedsEmergencyAffordance; + + private void requestCellScan() { + mHandler.obtainMessage(CELL_INFO_STATE_CHANGED).sendToTarget(); + } + + private SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionChangedListener + = new SubscriptionManager.OnSubscriptionsChangedListener() { + @Override + public void onSubscriptionsChanged() { + mHandler.obtainMessage(SUBSCRIPTION_CHANGED).sendToTarget(); + } + }; + + public EmergencyAffordanceService(Context context) { + super(context); + mContext = context; + int[] numbers = context.getResources().getIntArray( + com.android.internal.R.array.config_emergency_mcc_codes); + mEmergencyCallMccNumbers = new ArrayList<>(numbers.length); + for (int i = 0; i < numbers.length; i++) { + mEmergencyCallMccNumbers.add(numbers[i]); + } + } + + private void updateEmergencyAffordanceNeeded() { + synchronized (mLock) { + mEmergencyAffordanceNeeded = mSimNeedsEmergencyAffordance || + mNetworkNeedsEmergencyAffordance; + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.EMERGENCY_AFFORDANCE_NEEDED, + mEmergencyAffordanceNeeded ? 1 : 0); + if (mEmergencyAffordanceNeeded) { + stopScanning(); + } + } + } + + private void stopScanning() { + synchronized (mLock) { + mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); + mScansCompleted = 0; + } + } + + private boolean isEmergencyAffordanceNeeded() { + synchronized (mLock) { + return mEmergencyAffordanceNeeded; + } + } + + @Override + public void onStart() { + } + + @Override + public void onBootPhase(int phase) { + if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { + mTelephonyManager = mContext.getSystemService(TelephonyManager.class); + mSubscriptionManager = SubscriptionManager.from(mContext); + HandlerThread thread = new HandlerThread(TAG); + thread.start(); + mHandler = new MyHandler(thread.getLooper()); + mHandler.obtainMessage(INITIALIZE_STATE).sendToTarget(); + startScanning(); + IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED); + mContext.registerReceiver(mAirplaneModeReceiver, filter); + mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionChangedListener); + } + } + + private void startScanning() { + mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CELL_INFO + | PhoneStateListener.LISTEN_CELL_LOCATION); + } + + /** Handler to do the heavier work on */ + private class MyHandler extends Handler { + + public MyHandler(Looper l) { + super(l); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case INITIALIZE_STATE: + handleInitializeState(); + break; + case CELL_INFO_STATE_CHANGED: + handleUpdateCellInfo(); + break; + case SUBSCRIPTION_CHANGED: + handleUpdateSimSubscriptionInfo(); + break; + } + } + } + + private void handleInitializeState() { + if (handleUpdateSimSubscriptionInfo()) { + return; + } + if (handleUpdateCellInfo()) { + return; + } + updateEmergencyAffordanceNeeded(); + } + + private boolean handleUpdateSimSubscriptionInfo() { + boolean neededBefore = simNeededAffordanceBefore(); + boolean neededNow = neededBefore; + List<SubscriptionInfo> activeSubscriptionInfoList = + mSubscriptionManager.getActiveSubscriptionInfoList(); + if (activeSubscriptionInfoList == null) { + return neededNow; + } + for (SubscriptionInfo info : activeSubscriptionInfoList) { + int mcc = info.getMcc(); + if (mccRequiresEmergencyAffordance(mcc)) { + neededNow = true; + break; + } else if (mcc != 0 && mcc != Integer.MAX_VALUE){ + // a Sim with a different mcc code was found + neededNow = false; + } + String simOperator = mTelephonyManager.getSimOperator(info.getSubscriptionId()); + mcc = 0; + if (simOperator != null && simOperator.length() >= 3) { + mcc = Integer.parseInt(simOperator.substring(0, 3)); + } + if (mcc != 0) { + if (mccRequiresEmergencyAffordance(mcc)) { + neededNow = true; + break; + } else { + // a Sim with a different mcc code was found + neededNow = false; + } + } + } + if (neededNow != neededBefore) { + setSimNeedsEmergencyAffordance(neededNow); + } + return neededNow; + } + + private void setSimNeedsEmergencyAffordance(boolean simNeedsEmergencyAffordance) { + mSimNeedsEmergencyAffordance = simNeedsEmergencyAffordance; + Settings.Global.putInt(mContext.getContentResolver(), + EMERGENCY_SIM_INSERTED_SETTING, + simNeedsEmergencyAffordance ? 1 : 0); + updateEmergencyAffordanceNeeded(); + } + + private boolean simNeededAffordanceBefore() { + return Settings.Global.getInt(mContext.getContentResolver(), + "emergency_sim_inserted_before", 0) != 0; + } + + private boolean handleUpdateCellInfo() { + List<CellInfo> cellInfos = mTelephonyManager.getAllCellInfo(); + if (cellInfos == null) { + return false; + } + boolean stopScanningAfterScan = false; + for (CellInfo cellInfo : cellInfos) { + int mcc = 0; + if (cellInfo instanceof CellInfoGsm) { + mcc = ((CellInfoGsm) cellInfo).getCellIdentity().getMcc(); + } else if (cellInfo instanceof CellInfoLte) { + mcc = ((CellInfoLte) cellInfo).getCellIdentity().getMcc(); + } else if (cellInfo instanceof CellInfoWcdma) { + mcc = ((CellInfoWcdma) cellInfo).getCellIdentity().getMcc(); + } + if (mccRequiresEmergencyAffordance(mcc)) { + setNetworkNeedsEmergencyAffordance(true); + return true; + } else if (mcc != 0 && mcc != Integer.MAX_VALUE) { + // we found an mcc that isn't in the list, abort + stopScanningAfterScan = true; + } + } + if (stopScanningAfterScan) { + stopScanning(); + } else { + onCellScanFinishedUnsuccessful(); + } + setNetworkNeedsEmergencyAffordance(false); + return false; + } + + private void setNetworkNeedsEmergencyAffordance(boolean needsAffordance) { + synchronized (mLock) { + mNetworkNeedsEmergencyAffordance = needsAffordance; + updateEmergencyAffordanceNeeded(); + } + } + + private void onCellScanFinishedUnsuccessful() { + synchronized (mLock) { + mScansCompleted++; + if (mScansCompleted >= NUM_SCANS_UNTIL_ABORT) { + stopScanning(); + } + } + } + + private boolean mccRequiresEmergencyAffordance(int mcc) { + return mEmergencyCallMccNumbers.contains(mcc); + } +} diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java index bb91f76ecf30..a8bd4d289616 100644 --- a/services/core/java/com/android/server/policy/GlobalActions.java +++ b/services/core/java/com/android/server/policy/GlobalActions.java @@ -20,6 +20,7 @@ import com.android.internal.app.AlertController; import com.android.internal.app.AlertController.AlertParams; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; +import com.android.internal.policy.EmergencyAffordanceManager; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyProperties; import com.android.internal.R; @@ -27,7 +28,6 @@ import com.android.internal.widget.LockPatternUtils; import android.app.ActivityManager; import android.app.ActivityManagerNative; -import android.app.AlertDialog; import android.app.Dialog; import android.content.BroadcastReceiver; import android.content.Context; @@ -125,6 +125,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac private boolean mHasTelephony; private boolean mHasVibrator; private final boolean mShowSilentToggle; + private final EmergencyAffordanceManager mEmergencyAffordanceManager; /** * @param context everything needs a context :( @@ -159,6 +160,8 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mShowSilentToggle = SHOW_SILENT_TOGGLE && !mContext.getResources().getBoolean( com.android.internal.R.bool.config_useFixedVolume); + + mEmergencyAffordanceManager = new EmergencyAffordanceManager(context); } /** @@ -308,6 +311,10 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac addedKeys.add(actionKey); } + if (mEmergencyAffordanceManager.needsEmergencyAffordance()) { + mItems.add(getEmergencyAction()); + } + mAdapter = new MyAdapter(); AlertParams params = new AlertParams(mContext); @@ -493,6 +500,26 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac }; } + private Action getEmergencyAction() { + return new SinglePressAction(com.android.internal.R.drawable.emergency_icon, + R.string.global_action_emergency) { + @Override + public void onPress() { + mEmergencyAffordanceManager.performEmergencyCall(); + } + + @Override + public boolean showDuringKeyguard() { + return true; + } + + @Override + public boolean showBeforeProvisioning() { + return true; + } + }; + } + private Action getAssistAction() { return new SinglePressAction(com.android.internal.R.drawable.ic_action_assist_focused, R.string.global_action_assist) { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 555d9b1e3f20..0de6b7790856 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -16,7 +16,6 @@ package com.android.server; -import android.app.ActivityManagerNative; import android.app.ActivityThread; import android.app.INotificationManager; import android.app.usage.UsageStatsManagerInternal; @@ -32,7 +31,6 @@ import android.os.Build; import android.os.Environment; import android.os.FactoryTest; import android.os.FileUtils; -import android.os.IPowerManager; import android.os.Looper; import android.os.PowerManager; import android.os.RemoteException; @@ -55,6 +53,7 @@ import com.android.internal.app.NightDisplayController; import com.android.internal.os.BinderInternal; import com.android.internal.os.SamplingProfilerIntegration; import com.android.internal.os.ZygoteInit; +import com.android.internal.policy.EmergencyAffordanceManager; import com.android.internal.widget.ILockSettings; import com.android.server.accessibility.AccessibilityManagerService; import com.android.server.am.ActivityManagerService; @@ -67,6 +66,7 @@ import com.android.server.devicepolicy.DevicePolicyManagerService; import com.android.server.display.DisplayManagerService; import com.android.server.display.NightDisplayService; import com.android.server.dreams.DreamManagerService; +import com.android.server.emergency.EmergencyAffordanceService; import com.android.server.fingerprint.FingerprintService; import com.android.server.hdmi.HdmiControlService; import com.android.server.input.InputManagerService; @@ -1097,6 +1097,11 @@ public final class SystemServer { Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } + if (!disableNetwork && !disableNonCoreServices && EmergencyAffordanceManager.ENABLED) { + // EmergencyMode sevice + mSystemServiceManager.startService(EmergencyAffordanceService.class); + } + if (!disableNonCoreServices) { // Dreams (interactive idle-time views, a/k/a screen savers, and doze mode) mSystemServiceManager.startService(DreamManagerService.class); |