1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.telecom;
18
19import android.content.ContentResolver;
20import android.provider.Settings;
21import java.util.concurrent.TimeUnit;
22
23/**
24 * A helper class which serves only to make it easier to lookup timeout values. This class should
25 * never be instantiated, and only accessed through the {@link #get(String, long)} method.
26 *
27 * These methods are safe to call from any thread, including the UI thread.
28 */
29public final class Timeouts {
30    public static class Adapter {
31        public Adapter() { }
32
33        public long getCallScreeningTimeoutMillis(ContentResolver cr) {
34            return Timeouts.getCallScreeningTimeoutMillis(cr);
35        }
36
37        public long getCallRemoveUnbindInCallServicesDelay(ContentResolver cr) {
38            return Timeouts.getCallRemoveUnbindInCallServicesDelay(cr);
39        }
40
41        public long getRetryBluetoothConnectAudioBackoffMillis(ContentResolver cr) {
42            return Timeouts.getRetryBluetoothConnectAudioBackoffMillis(cr);
43        }
44
45        public long getBluetoothPendingTimeoutMillis(ContentResolver cr) {
46            return Timeouts.getBluetoothPendingTimeoutMillis(cr);
47        }
48
49        public long getEmergencyCallbackWindowMillis(ContentResolver cr) {
50            return Timeouts.getEmergencyCallbackWindowMillis(cr);
51        }
52    }
53
54    /** A prefix to use for all keys so to not clobber the global namespace. */
55    private static final String PREFIX = "telecom.";
56
57    private Timeouts() {}
58
59    /**
60     * Returns the timeout value from Settings or the default value if it hasn't been changed. This
61     * method is safe to call from any thread, including the UI thread.
62     *
63     * @param contentResolver The content resolved.
64     * @param key Settings key to retrieve.
65     * @param defaultValue Default value, in milliseconds.
66     * @return The timeout value from Settings or the default value if it hasn't been changed.
67     */
68    private static long get(ContentResolver contentResolver, String key, long defaultValue) {
69        return Settings.Secure.getLong(contentResolver, PREFIX + key, defaultValue);
70    }
71
72    /**
73     * Returns the amount of time to wait before disconnecting a call that was canceled via
74     * NEW_OUTGOING_CALL broadcast. This timeout allows apps which repost the call using a gateway
75     * to reuse the existing call, preventing the call from causing a start->end->start jank in the
76     * in-call UI.
77     */
78    public static long getNewOutgoingCallCancelMillis(ContentResolver contentResolver) {
79        return get(contentResolver, "new_outgoing_call_cancel_ms", 500L);
80    }
81
82    /**
83     * Returns the maximum amount of time to wait before disconnecting a call that was canceled via
84     * NEW_OUTGOING_CALL broadcast. This prevents malicious or poorly configured apps from
85     * forever tying up the Telecom stack.
86     */
87    public static long getMaxNewOutgoingCallCancelMillis(ContentResolver contentResolver) {
88        return get(contentResolver, "max_new_outgoing_call_cancel_ms", 10000L);
89    }
90
91    /**
92     * Returns the amount of time to play each DTMF tone after post dial continue.
93     * This timeout allows the current tone to play for a certain amount of time before either being
94     * interrupted by the next tone or terminated.
95     */
96    public static long getDelayBetweenDtmfTonesMillis(ContentResolver contentResolver) {
97        return get(contentResolver, "delay_between_dtmf_tones_ms", 300L);
98    }
99
100    /**
101     * Returns the amount of time to wait for an emergency call to be placed before routing to
102     * a different call service. A value of 0 or less means no timeout should be used.
103     */
104    public static long getEmergencyCallTimeoutMillis(ContentResolver contentResolver) {
105        return get(contentResolver, "emergency_call_timeout_millis", 25000L /* 25 seconds */);
106    }
107
108    /**
109     * Returns the amount of time to wait for an emergency call to be placed before routing to
110     * a different call service. This timeout is used only when the radio is powered off (for
111     * example in airplane mode). A value of 0 or less means no timeout should be used.
112     */
113    public static long getEmergencyCallTimeoutRadioOffMillis(ContentResolver contentResolver) {
114        return get(contentResolver, "emergency_call_timeout_radio_off_millis",
115                60000L /* 1 minute */);
116    }
117
118    /**
119     * Returns the amount of delay before unbinding the in-call services after all the calls
120     * are removed.
121     */
122    public static long getCallRemoveUnbindInCallServicesDelay(ContentResolver contentResolver) {
123        return get(contentResolver, "call_remove_unbind_in_call_services_delay",
124                2000L /* 2 seconds */);
125    }
126
127    /**
128     * Returns the amount of time for which bluetooth is considered connected after requesting
129     * connection. This compensates for the amount of time it takes for the audio route to
130     * actually change to bluetooth.
131     */
132    public static long getBluetoothPendingTimeoutMillis(ContentResolver contentResolver) {
133        return get(contentResolver, "bluetooth_pending_timeout_millis", 5000L);
134    }
135
136    /**
137     * Returns the amount of time to wait before retrying the connectAudio call. This is
138     * necessary to account for the HeadsetStateMachine sometimes not being ready when we want to
139     * connect to bluetooth audio immediately after a device connects.
140     */
141    public static long getRetryBluetoothConnectAudioBackoffMillis(ContentResolver contentResolver) {
142        return get(contentResolver, "retry_bluetooth_connect_audio_backoff_millis", 500L);
143    }
144
145    /**
146     * Returns the amount of time to wait for the call screening service to allow or disallow a
147     * call.
148     */
149    public static long getCallScreeningTimeoutMillis(ContentResolver contentResolver) {
150        return get(contentResolver, "call_screening_timeout", 5000L /* 5 seconds */);
151    }
152
153    /**
154     * Returns the amount of time after an emergency call that incoming calls should be treated
155     * as potential emergency callbacks.
156     */
157    public static long getEmergencyCallbackWindowMillis(ContentResolver contentResolver) {
158      return get(contentResolver, "emergency_callback_window_millis",
159          TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES));
160    }
161}
162