1b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos/*
2b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos * Copyright (C) 2014 The Android Open Source Project
3b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos *
4b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos * Licensed under the Apache License, Version 2.0 (the "License");
5b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos * you may not use this file except in compliance with the License.
6b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos * You may obtain a copy of the License at
7b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos *
8b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos *      http://www.apache.org/licenses/LICENSE-2.0
9b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos *
10b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos * Unless required by applicable law or agreed to in writing, software
11b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos * distributed under the License is distributed on an "AS IS" BASIS,
12b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos * See the License for the specific language governing permissions and
14b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos * limitations under the License
15b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos */
16b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos
17b83777ba5c12295224cd566bba59a44b8860e449Adrian Roospackage com.android.systemui.qs.tiles;
18b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos
19bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport android.app.ActivityManager;
20bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport android.os.SystemClock;
21bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock
22b83777ba5c12295224cd566bba59a44b8860e449Adrian Roosimport com.android.systemui.R;
23b83777ba5c12295224cd566bba59a44b8860e449Adrian Roosimport com.android.systemui.qs.QSTile;
24b83777ba5c12295224cd566bba59a44b8860e449Adrian Roosimport com.android.systemui.statusbar.policy.FlashlightController;
25b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos
26b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos/** Quick settings tile: Control flashlight **/
27b83777ba5c12295224cd566bba59a44b8860e449Adrian Roospublic class FlashlightTile extends QSTile<QSTile.BooleanState> implements
28b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos        FlashlightController.FlashlightListener {
29b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos
30034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos    /** Grace period for which we consider the flashlight
31034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos     * still available because it was recently on. */
32034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos    private static final long RECENTLY_ON_DURATION_MILLIS = 500;
33034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos
34c6df3cf273a6464005699796d148be0bfdf9e8c3John Spurlock    private final AnimationIcon mEnable
35c6df3cf273a6464005699796d148be0bfdf9e8c3John Spurlock            = new AnimationIcon(R.drawable.ic_signal_flashlight_enable_animation);
36c6df3cf273a6464005699796d148be0bfdf9e8c3John Spurlock    private final AnimationIcon mDisable
37c6df3cf273a6464005699796d148be0bfdf9e8c3John Spurlock            = new AnimationIcon(R.drawable.ic_signal_flashlight_disable_animation);
38b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    private final FlashlightController mFlashlightController;
39034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos    private long mWasLastOn;
40b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos
41b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    public FlashlightTile(Host host) {
42b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos        super(host);
43b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos        mFlashlightController = host.getFlashlightController();
44b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos        mFlashlightController.addListener(this);
45b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    }
46b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos
47b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    @Override
48bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    protected void handleDestroy() {
49bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        super.handleDestroy();
50bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock        mFlashlightController.removeListener(this);
51bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    }
52bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock
53bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock    @Override
54b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    protected BooleanState newTileState() {
55b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos        return new BooleanState();
56b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    }
57b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos
58b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    @Override
59b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    public void setListening(boolean listening) {
60b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    }
61b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos
62b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    @Override
63b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    protected void handleUserSwitch(int newUserId) {
64b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    }
65b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos
66b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    @Override
67b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    protected void handleClick() {
682649f6b22a2dbaed6faea4aba25020bd55a14c18Guang Zhu        if (ActivityManager.isUserAMonkey()) {
692649f6b22a2dbaed6faea4aba25020bd55a14c18Guang Zhu            return;
702649f6b22a2dbaed6faea4aba25020bd55a14c18Guang Zhu        }
71b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos        boolean newState = !mState.value;
72b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos        mFlashlightController.setFlashlight(newState);
73c6df3cf273a6464005699796d148be0bfdf9e8c3John Spurlock        refreshState(newState ? UserBoolean.USER_TRUE : UserBoolean.USER_FALSE);
74b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    }
75b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos
76b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    @Override
77b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    protected void handleUpdateState(BooleanState state, Object arg) {
78034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos        if (state.value) {
79034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos            mWasLastOn = SystemClock.uptimeMillis();
80034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos        }
81034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos
82c6df3cf273a6464005699796d148be0bfdf9e8c3John Spurlock        if (arg instanceof UserBoolean) {
83c6df3cf273a6464005699796d148be0bfdf9e8c3John Spurlock            state.value = ((UserBoolean) arg).value;
84b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos        }
85034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos
86034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos        if (!state.value && mWasLastOn != 0) {
87034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos            if (SystemClock.uptimeMillis() > mWasLastOn + RECENTLY_ON_DURATION_MILLIS) {
88034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos                mWasLastOn = 0;
89034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos            } else {
90034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos                mHandler.removeCallbacks(mRecentlyOnTimeout);
91034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos                mHandler.postAtTime(mRecentlyOnTimeout, mWasLastOn + RECENTLY_ON_DURATION_MILLIS);
92034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos            }
93034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos        }
94034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos
95034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos        // Always show the tile when the flashlight is or was recently on. This is needed because
96930aaa717eee0f5a578ba2cf68da95e725914609Adrian Roos        // the camera is not available while it is being used for the flashlight.
97034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos        state.visible = mWasLastOn != 0 || mFlashlightController.isAvailable();
98b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos        state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
99c6df3cf273a6464005699796d148be0bfdf9e8c3John Spurlock        final AnimationIcon icon = state.value ? mEnable : mDisable;
100c6df3cf273a6464005699796d148be0bfdf9e8c3John Spurlock        icon.setAllowAnimation(arg instanceof UserBoolean && ((UserBoolean) arg).userInitiated);
101c6df3cf273a6464005699796d148be0bfdf9e8c3John Spurlock        state.icon = icon;
1024fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek        int onOrOffId = state.value
1034fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek                ? R.string.accessibility_quick_settings_flashlight_on
1044fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek                : R.string.accessibility_quick_settings_flashlight_off;
1054fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek        state.contentDescription = mContext.getString(onOrOffId);
1064fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek    }
1074fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek
1084fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek    @Override
1094fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek    protected String composeChangeAnnouncement() {
1104fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek        if (mState.value) {
1114fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek            return mContext.getString(R.string.accessibility_quick_settings_flashlight_changed_on);
1124fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek        } else {
1134fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek            return mContext.getString(R.string.accessibility_quick_settings_flashlight_changed_off);
1144fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek        }
115b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    }
116b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos
117b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    @Override
118b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    public void onFlashlightOff() {
119c6df3cf273a6464005699796d148be0bfdf9e8c3John Spurlock        refreshState(UserBoolean.BACKGROUND_FALSE);
120b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    }
121b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos
122b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    @Override
123b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    public void onFlashlightError() {
124c6df3cf273a6464005699796d148be0bfdf9e8c3John Spurlock        refreshState(UserBoolean.BACKGROUND_FALSE);
125b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos    }
126930aaa717eee0f5a578ba2cf68da95e725914609Adrian Roos
127930aaa717eee0f5a578ba2cf68da95e725914609Adrian Roos    @Override
128930aaa717eee0f5a578ba2cf68da95e725914609Adrian Roos    public void onFlashlightAvailabilityChanged(boolean available) {
129930aaa717eee0f5a578ba2cf68da95e725914609Adrian Roos        refreshState();
130930aaa717eee0f5a578ba2cf68da95e725914609Adrian Roos    }
131034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos
132034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos    private Runnable mRecentlyOnTimeout = new Runnable() {
133034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos        @Override
134034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos        public void run() {
135034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos            refreshState();
136034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos        }
137034a6c9667b41506b0f6fa94617037717d7a9cd6Adrian Roos    };
138b83777ba5c12295224cd566bba59a44b8860e449Adrian Roos}
139