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:
@@ -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(']');
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
50
packages/SystemUI/res/drawable/ic_hotspot_transient.xml
Normal file
50
packages/SystemUI/res/drawable/ic_hotspot_transient.xml
Normal file
File diff suppressed because one or more lines are too long
@@ -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>
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user