QS: Add transient icon for hotspot

Will make the loading time more clear.

Test: visual
Bug: 32270851
Change-Id: I0ea7591da132ff65fb7fc16b03b2891891e66598
This commit is contained in:
Jason Monk
2017-03-31 13:19:26 -04:00
parent 537fd18eaf
commit e645aee45a
11 changed files with 220 additions and 17 deletions

View File

@@ -105,6 +105,7 @@ public interface QSTile {
public CharSequence dualLabelContentDescription;
public boolean disabledByPolicy;
public boolean dualTarget = false;
public boolean isTransient = false;
public String expandedAccessibilityClassName;
public boolean copyTo(State other) {
@@ -119,6 +120,7 @@ public interface QSTile {
expandedAccessibilityClassName)
|| !Objects.equals(other.disabledByPolicy, disabledByPolicy)
|| !Objects.equals(other.state, state)
|| !Objects.equals(other.isTransient, isTransient)
|| !Objects.equals(other.dualTarget, dualTarget);
other.icon = icon;
other.label = label;
@@ -128,6 +130,7 @@ public interface QSTile {
other.disabledByPolicy = disabledByPolicy;
other.state = state;
other.dualTarget = dualTarget;
other.isTransient = isTransient;
return changed;
}
@@ -145,6 +148,7 @@ public interface QSTile {
sb.append(",expandedAccessibilityClassName=").append(expandedAccessibilityClassName);
sb.append(",disabledByPolicy=").append(disabledByPolicy);
sb.append(",dualTarget=").append(dualTarget);
sb.append(",isTransient=").append(isTransient);
sb.append(",state=").append(state);
return sb.append(']');
}

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android" >
<set
android:ordering="sequentially" >
<objectAnimator
android:duration="266"
android:propertyName="fillAlpha"
android:valueFrom="1.0"
android:valueTo="1.0"
android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
<objectAnimator
android:duration="16"
android:propertyName="fillAlpha"
android:valueFrom="1.0"
android:valueTo="0.5"
android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
<objectAnimator
android:duration="433"
android:propertyName="fillAlpha"
android:valueFrom="0.5"
android:valueTo="0.5"
android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
<objectAnimator
android:duration="16"
android:propertyName="fillAlpha"
android:valueFrom="0.5"
android:valueTo="1.0"
android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
</set>
</set>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android" >
<set
android:ordering="sequentially" >
<objectAnimator
android:duration="133"
android:propertyName="fillAlpha"
android:valueFrom="1.0"
android:valueTo="1.0"
android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
<objectAnimator
android:duration="16"
android:propertyName="fillAlpha"
android:valueFrom="1.0"
android:valueTo="0.5"
android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
<objectAnimator
android:duration="433"
android:propertyName="fillAlpha"
android:valueFrom="0.5"
android:valueTo="0.5"
android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
<objectAnimator
android:duration="16"
android:propertyName="fillAlpha"
android:valueFrom="0.5"
android:valueTo="1.0"
android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
</set>
</set>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android" >
<set
android:ordering="sequentially" >
<objectAnimator
android:duration="16"
android:propertyName="fillAlpha"
android:valueFrom="1.0"
android:valueTo="0.5"
android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
<objectAnimator
android:duration="433"
android:propertyName="fillAlpha"
android:valueFrom="0.5"
android:valueTo="0.5"
android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
<objectAnimator
android:duration="16"
android:propertyName="fillAlpha"
android:valueFrom="0.5"
android:valueTo="1.0"
android:valueType="floatType"
android:interpolator="@android:interpolator/linear" />
</set>
</set>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_hotspot_transient" >
<target
android:name="circle_3"
android:animation="@anim/ic_hotspot_transient_circle_3_animation" />
<target
android:name="circle_2"
android:animation="@anim/ic_hotspot_transient_circle_2_animation" />
<target
android:name="circle_1"
android:animation="@anim/ic_hotspot_transient_circle_1_animation" />
</animated-vector>

View File

@@ -22,6 +22,8 @@ import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Animatable2;
import android.graphics.drawable.Animatable2.AnimationCallback;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.ImageView;
@@ -96,11 +98,16 @@ public class QSIconViewImpl extends QSIconView {
iv.setImageDrawable(d);
iv.setTag(R.id.qs_icon_tag, state.icon);
iv.setPadding(0, padding, 0, padding);
if (d instanceof Animatable && iv.isShown()) {
Animatable a = (Animatable) d;
if (d instanceof Animatable2) {
Animatable2 a = (Animatable2) d;
a.start();
if (!iv.isShown()) {
a.stop(); // skip directly to end state
if (state.isTransient) {
a.registerAnimationCallback(new AnimationCallback() {
@Override
public void onAnimationEnd(Drawable drawable) {
a.start();
}
});
}
}
}

View File

@@ -25,7 +25,6 @@ import android.provider.Settings.Global;
import android.service.quicksettings.Tile;
import android.widget.Switch;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -43,6 +42,7 @@ public class HotspotTile extends QSTileImpl<AirplaneBooleanState> {
private final AnimationIcon mEnable =
new AnimationIcon(R.drawable.ic_hotspot_enable_animation,
R.drawable.ic_hotspot_disable);
private final Icon mEnabledStatic = ResourceIcon.get(R.drawable.ic_hotspot_disable);
private final AnimationIcon mDisable =
new AnimationIcon(R.drawable.ic_hotspot_disable_animation,
R.drawable.ic_hotspot_enable);
@@ -124,10 +124,15 @@ public class HotspotTile extends QSTileImpl<AirplaneBooleanState> {
} else {
state.value = mController.isHotspotEnabled();
}
state.icon = state.value ? mEnable : mDisable;
state.icon = !state.value ? mDisable
: state.isTransient ? mEnabledStatic
: mEnable;
boolean wasAirplane = state.isAirplaneMode;
state.isAirplaneMode = mAirplaneMode.getValue() != 0;
if (state.isAirplaneMode) {
state.isTransient = mController.isHotspotTransient();
if (state.isTransient) {
state.icon = ResourceIcon.get(R.drawable.ic_hotspot_transient_animation);
} else if (state.isAirplaneMode) {
state.icon = mUnavailable;
} else if (wasAirplane) {
state.icon = mDisableNoAnimation;
@@ -135,7 +140,7 @@ public class HotspotTile extends QSTileImpl<AirplaneBooleanState> {
state.expandedAccessibilityClassName = Switch.class.getName();
state.contentDescription = state.label;
state.state = state.isAirplaneMode ? Tile.STATE_UNAVAILABLE
: state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
: state.value || state.isTransient ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
}
@Override

View File

@@ -21,6 +21,8 @@ import com.android.systemui.statusbar.policy.HotspotController.Callback;
public interface HotspotController extends CallbackController<Callback>, Dumpable {
boolean isHotspotEnabled();
boolean isHotspotTransient();
void setHotspotEnabled(boolean enabled);
boolean isHotspotSupported();

View File

@@ -23,6 +23,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.UserManager;
import android.util.Log;
@@ -41,6 +42,7 @@ public class HotspotControllerImpl implements HotspotController {
private final Context mContext;
private int mHotspotState;
private boolean mWaitingForCallback;
public HotspotControllerImpl(Context context) {
mContext = context;
@@ -101,22 +103,20 @@ public class HotspotControllerImpl implements HotspotController {
return mHotspotState == WifiManager.WIFI_AP_STATE_ENABLED;
}
static final class OnStartTetheringCallback extends
ConnectivityManager.OnStartTetheringCallback {
@Override
public void onTetheringStarted() {}
@Override
public void onTetheringFailed() {
// TODO: Show error.
}
@Override
public boolean isHotspotTransient() {
return mWaitingForCallback || (mHotspotState == WifiManager.WIFI_AP_STATE_ENABLING);
}
@Override
public void setHotspotEnabled(boolean enabled) {
if (enabled) {
OnStartTetheringCallback callback = new OnStartTetheringCallback();
mWaitingForCallback = true;
if (DEBUG) Log.d(TAG, "Starting tethering");
mConnectivityManager.startTethering(
ConnectivityManager.TETHERING_WIFI, false, callback);
fireCallback(isHotspotEnabled());
} else {
mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI);
}
@@ -130,6 +130,24 @@ public class HotspotControllerImpl implements HotspotController {
}
}
private final class OnStartTetheringCallback extends
ConnectivityManager.OnStartTetheringCallback {
@Override
public void onTetheringStarted() {
if (DEBUG) Log.d(TAG, "onTetheringStarted");
mWaitingForCallback = false;
// Don't fire a callback here, instead wait for the next update from wifi.
}
@Override
public void onTetheringFailed() {
if (DEBUG) Log.d(TAG, "onTetheringFailed");
mWaitingForCallback = false;
fireCallback(isHotspotEnabled());
// TODO: Show error.
}
}
private final class Receiver extends BroadcastReceiver {
private boolean mRegistered;
@@ -149,9 +167,9 @@ public class HotspotControllerImpl implements HotspotController {
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) Log.d(TAG, "onReceive " + intent.getAction());
int state = intent.getIntExtra(
WifiManager.EXTRA_WIFI_AP_STATE, WifiManager.WIFI_AP_STATE_FAILED);
if (DEBUG) Log.d(TAG, "onReceive " + state);
mHotspotState = state;
fireCallback(mHotspotState == WifiManager.WIFI_AP_STATE_ENABLED);
}

View File

@@ -30,6 +30,11 @@ public class FakeHotspotController extends BaseLeakChecker<Callback> implements
return false;
}
@Override
public boolean isHotspotTransient() {
return false;
}
@Override
public void setHotspotEnabled(boolean enabled) {