1/*
2 * Copyright (C) 2015 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 */
16package android.service.quicksettings;
17
18import android.content.ComponentName;
19import android.graphics.drawable.Icon;
20import android.os.Parcel;
21import android.os.Parcelable;
22import android.os.RemoteException;
23import android.text.TextUtils;
24import android.util.Log;
25
26/**
27 * A Tile holds the state of a tile that will be displayed
28 * in Quick Settings.
29 *
30 * A tile in Quick Settings exists as an icon with an accompanied label.
31 * It also may have content description for accessibility usability.
32 * The style and layout of the tile may change to match a given
33 * device.
34 */
35public final class Tile implements Parcelable {
36
37    private static final String TAG = "Tile";
38
39    /**
40     * An unavailable state indicates that for some reason this tile is not currently
41     * available to the user for some reason, and will have no click action.  The tile's
42     * icon will be tinted differently to reflect this state.
43     */
44    public static final int STATE_UNAVAILABLE = 0;
45
46    /**
47     * This represents a tile that is currently in a disabled state but is still interactable.
48     *
49     * A disabled state indicates that the tile is not currently active (e.g. wifi disconnected or
50     * bluetooth disabled), but is still interactable by the user to modify this state.  Tiles
51     * that have boolean states should use this to represent one of their states.  The tile's
52     * icon will be tinted differently to reflect this state, but still be distinct from unavailable.
53     */
54    public static final int STATE_INACTIVE = 1;
55
56    /**
57     * This represents a tile that is currently active. (e.g. wifi is connected, bluetooth is on,
58     * cast is casting).  This is the default state.
59     */
60    public static final int STATE_ACTIVE = 2;
61
62    private ComponentName mComponentName;
63    private Icon mIcon;
64    private CharSequence mLabel;
65    private CharSequence mContentDescription;
66    // Default to active until clients of the new API can update.
67    private int mState = STATE_ACTIVE;
68
69    private IQSService mService;
70
71    /**
72     * @hide
73     */
74    public Tile(Parcel source) {
75        readFromParcel(source);
76    }
77
78    /**
79     * @hide
80     */
81    public Tile(ComponentName componentName) {
82        mComponentName = componentName;
83    }
84
85    /**
86     * @hide
87     */
88    public void setService(IQSService service) {
89        mService = service;
90    }
91
92    /**
93     * @hide
94     */
95    public ComponentName getComponentName() {
96        return mComponentName;
97    }
98
99    /**
100     * @hide
101     */
102    public IQSService getQsService() {
103        return mService;
104    }
105
106    /**
107     * The current state of the tile.
108     *
109     * @see #STATE_UNAVAILABLE
110     * @see #STATE_INACTIVE
111     * @see #STATE_ACTIVE
112     */
113    public int getState() {
114        return mState;
115    }
116
117    /**
118     * Sets the current state for the tile.
119     *
120     * Does not take effect until {@link #updateTile()} is called.
121     *
122     * @param state One of {@link #STATE_UNAVAILABLE}, {@link #STATE_INACTIVE},
123     * {@link #STATE_ACTIVE}
124     */
125    public void setState(int state) {
126        mState = state;
127    }
128
129    /**
130     * Gets the current icon for the tile.
131     */
132    public Icon getIcon() {
133        return mIcon;
134    }
135
136    /**
137     * Sets the current icon for the tile.
138     *
139     * This icon is expected to be white on alpha, and may be
140     * tinted by the system to match it's theme.
141     *
142     * Does not take effect until {@link #updateTile()} is called.
143     *
144     * @param icon New icon to show.
145     */
146    public void setIcon(Icon icon) {
147        this.mIcon = icon;
148    }
149
150    /**
151     * Gets the current label for the tile.
152     */
153    public CharSequence getLabel() {
154        return mLabel;
155    }
156
157    /**
158     * Sets the current label for the tile.
159     *
160     * Does not take effect until {@link #updateTile()} is called.
161     *
162     * @param label New label to show.
163     */
164    public void setLabel(CharSequence label) {
165        this.mLabel = label;
166    }
167
168    /**
169     * Gets the current content description for the tile.
170     */
171    public CharSequence getContentDescription() {
172        return mContentDescription;
173    }
174
175    /**
176     * Sets the current content description for the tile.
177     *
178     * Does not take effect until {@link #updateTile()} is called.
179     *
180     * @param contentDescription New content description to use.
181     */
182    public void setContentDescription(CharSequence contentDescription) {
183        this.mContentDescription = contentDescription;
184    }
185
186    @Override
187    public int describeContents() {
188        return 0;
189    }
190
191    /**
192     * Pushes the state of the Tile to Quick Settings to be displayed.
193     */
194    public void updateTile() {
195        try {
196            mService.updateQsTile(this);
197        } catch (RemoteException e) {
198            Log.e(TAG, "Couldn't update tile");
199        }
200    }
201
202    @Override
203    public void writeToParcel(Parcel dest, int flags) {
204        if (mComponentName != null) {
205            dest.writeByte((byte) 1);
206            mComponentName.writeToParcel(dest, flags);
207        } else {
208            dest.writeByte((byte) 0);
209        }
210        if (mIcon != null) {
211            dest.writeByte((byte) 1);
212            mIcon.writeToParcel(dest, flags);
213        } else {
214            dest.writeByte((byte) 0);
215        }
216        dest.writeInt(mState);
217        TextUtils.writeToParcel(mLabel, dest, flags);
218        TextUtils.writeToParcel(mContentDescription, dest, flags);
219    }
220
221    private void readFromParcel(Parcel source) {
222        if (source.readByte() != 0) {
223            mComponentName = ComponentName.CREATOR.createFromParcel(source);
224        } else {
225            mComponentName = null;
226        }
227        if (source.readByte() != 0) {
228            mIcon = Icon.CREATOR.createFromParcel(source);
229        } else {
230            mIcon = null;
231        }
232        mState = source.readInt();
233        mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
234        mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
235    }
236
237    public static final Creator<Tile> CREATOR = new Creator<Tile>() {
238        @Override
239        public Tile createFromParcel(Parcel source) {
240            return new Tile(source);
241        }
242
243        @Override
244        public Tile[] newArray(int size) {
245            return new Tile[size];
246        }
247    };
248}