diff options
Diffstat (limited to 'packages/SystemUI/src/com/android/systemui')
28 files changed, 875 insertions, 402 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java index 6ea5c70..89a2c74 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java @@ -28,6 +28,7 @@ public interface DozeHost { void pulseWhileDozing(@NonNull PulseCallback callback, int reason); void stopDozing(); boolean isPowerSaveActive(); + boolean isNotificationLightOn(); public interface Callback { void onNewNotifications(); @@ -40,4 +41,4 @@ public interface DozeHost { void onPulseStarted(); void onPulseFinished(); } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java index 7eb9c6e..1f3a830 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java @@ -153,7 +153,7 @@ public class DozeLog { sProxStats[pulseReason][near ? 0 : 1].append(); } - private static String pulseReasonToString(int pulseReason) { + public static String pulseReasonToString(int pulseReason) { switch (pulseReason) { case PULSE_REASON_INTENT: return "intent"; case PULSE_REASON_NOTIFICATION: return "notification"; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java index 1e29476..36995ff 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java @@ -56,6 +56,17 @@ public class DozeService extends DreamService { private static final String NOTIFICATION_PULSE_ACTION = ACTION_BASE + ".notification_pulse"; private static final String EXTRA_INSTANCE = "instance"; + /** + * Earliest time we pulse due to a notification light after the service started. + * + * <p>Incoming notification light events during the blackout period are + * delayed to the earliest time defined by this constant.</p> + * + * <p>This delay avoids a pulse immediately after screen off, at which + * point the notification light is re-enabled again by NoMan.</p> + */ + private static final int EARLIEST_LIGHT_PULSE_AFTER_START_MS = 10 * 1000; + private final String mTag = String.format(TAG + ".%08x", hashCode()); private final Context mContext = this; private final DozeParameters mDozeParameters = new DozeParameters(mContext); @@ -77,6 +88,7 @@ public class DozeService extends DreamService { private boolean mPowerSaveActive; private boolean mCarMode; private long mNotificationPulseTime; + private long mEarliestPulseDueToLight; private int mScheduleResetsRemaining; public DozeService() { @@ -161,8 +173,9 @@ public class DozeService extends DreamService { } mDreaming = true; - listenForPulseSignals(true); rescheduleNotificationPulse(false /*predicate*/); // cancel any pending pulse alarms + mEarliestPulseDueToLight = System.currentTimeMillis() + EARLIEST_LIGHT_PULSE_AFTER_START_MS; + listenForPulseSignals(true); // Ask the host to get things ready to start dozing. // Once ready, we call startDozing() at which point the CPU may suspend @@ -204,7 +217,9 @@ public class DozeService extends DreamService { // Here we need a wakelock to stay awake until the pulse is finished. mWakeLock.acquire(); mPulsing = true; - if (!mDozeParameters.getProxCheckBeforePulse()) { + if (!mDozeParameters.getProxCheckBeforePulse() || + reason == DozeLog.PULSE_REASON_SENSOR_PICKUP + && mDozeParameters.getPickupPerformsProxCheck()) { // skip proximity check continuePulsing(reason); return; @@ -298,6 +313,12 @@ public class DozeService extends DreamService { if (listen) { resetNotificationResets(); mHost.addCallback(mHostCallback); + + // Continue to pulse for existing LEDs. + mNotificationLightOn = mHost.isNotificationLightOn(); + if (mNotificationLightOn) { + updateNotificationPulseDueToLight(); + } } else { mHost.removeCallback(mHostCallback); } @@ -308,21 +329,27 @@ public class DozeService extends DreamService { mScheduleResetsRemaining = mDozeParameters.getPulseScheduleResets(); } - private void updateNotificationPulse() { - if (DEBUG) Log.d(mTag, "updateNotificationPulse"); + private void updateNotificationPulseDueToLight() { + long timeMs = System.currentTimeMillis(); + timeMs = Math.max(timeMs, mEarliestPulseDueToLight); + updateNotificationPulse(timeMs); + } + + private void updateNotificationPulse(long notificationTimeMs) { + if (DEBUG) Log.d(mTag, "updateNotificationPulse notificationTimeMs=" + notificationTimeMs); if (!mDozeParameters.getPulseOnNotifications()) return; if (mScheduleResetsRemaining <= 0) { if (DEBUG) Log.d(mTag, "No more schedule resets remaining"); return; } - final long now = System.currentTimeMillis(); - if ((now - mNotificationPulseTime) < mDozeParameters.getPulseDuration()) { + final long pulseDuration = mDozeParameters.getPulseDuration(false /*pickup*/); + if ((notificationTimeMs - mNotificationPulseTime) < pulseDuration) { if (DEBUG) Log.d(mTag, "Recently updated, not resetting schedule"); return; } mScheduleResetsRemaining--; if (DEBUG) Log.d(mTag, "mScheduleResetsRemaining = " + mScheduleResetsRemaining); - mNotificationPulseTime = now; + mNotificationPulseTime = notificationTimeMs; rescheduleNotificationPulse(true /*predicate*/); } @@ -404,14 +431,14 @@ public class DozeService extends DreamService { private final DozeHost.Callback mHostCallback = new DozeHost.Callback() { @Override public void onNewNotifications() { - if (DEBUG) Log.d(mTag, "onNewNotifications"); + if (DEBUG) Log.d(mTag, "onNewNotifications (noop)"); // noop for now } @Override public void onBuzzBeepBlinked() { if (DEBUG) Log.d(mTag, "onBuzzBeepBlinked"); - updateNotificationPulse(); + updateNotificationPulse(System.currentTimeMillis()); } @Override @@ -420,7 +447,7 @@ public class DozeService extends DreamService { if (mNotificationLightOn == on) return; mNotificationLightOn = on; if (mNotificationLightOn) { - updateNotificationPulse(); + updateNotificationPulseDueToLight(); } } diff --git a/packages/SystemUI/src/com/android/systemui/egg/LLand.java b/packages/SystemUI/src/com/android/systemui/egg/LLand.java index cdfe6e5..5de09a3 100644 --- a/packages/SystemUI/src/com/android/systemui/egg/LLand.java +++ b/packages/SystemUI/src/com/android/systemui/egg/LLand.java @@ -29,11 +29,15 @@ import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; +import android.media.AudioAttributes; +import android.media.AudioManager; +import android.os.Vibrator; import android.util.AttributeSet; import android.util.Log; import android.view.Gravity; import android.view.KeyEvent; import android.view.MotionEvent; +import android.util.Slog; import android.view.View; import android.view.ViewOutlineProvider; import android.view.animation.DecelerateInterpolator; @@ -51,9 +55,9 @@ public class LLand extends FrameLayout { public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); public static final boolean DEBUG_DRAW = false; // DEBUG - public static final void L(String s, Object ... objects) { + public static void L(String s, Object ... objects) { if (DEBUG) { - Log.d(TAG, String.format(s, objects)); + Slog.d(TAG, objects.length == 0 ? s : String.format(s, objects)); } } @@ -61,17 +65,18 @@ public class LLand extends FrameLayout { public static final boolean HAVE_STARS = true; public static final float DEBUG_SPEED_MULTIPLIER = 1f; // 0.1f; - public static final boolean DEBUG_IDDQD = false; + public static final boolean DEBUG_IDDQD = Log.isLoggable(TAG + ".iddqd", Log.DEBUG); final static int[] POPS = { - // resid // spinny! - R.drawable.pop_belt, 0, - R.drawable.pop_droid, 0, - R.drawable.pop_pizza, 1, - R.drawable.pop_stripes, 0, - R.drawable.pop_swirl, 1, - R.drawable.pop_vortex, 1, - R.drawable.pop_vortex2, 1, + // resid // spinny! // alpha + R.drawable.pop_belt, 0, 255, + R.drawable.pop_droid, 0, 255, + R.drawable.pop_pizza, 1, 255, + R.drawable.pop_stripes, 0, 255, + R.drawable.pop_swirl, 1, 255, + R.drawable.pop_vortex, 1, 255, + R.drawable.pop_vortex2, 1, 255, + R.drawable.pop_ball, 0, 190, }; private static class Params { @@ -117,10 +122,20 @@ public class LLand extends FrameLayout { PLAYER_Z = res.getDimensionPixelSize(R.dimen.player_z); PLAYER_Z_BOOST = res.getDimensionPixelSize(R.dimen.player_z_boost); HUD_Z = res.getDimensionPixelSize(R.dimen.hud_z); + + // Sanity checking + if (OBSTACLE_MIN <= OBSTACLE_WIDTH / 2) { + Slog.e(TAG, "error: obstacles might be too short, adjusting"); + OBSTACLE_MIN = OBSTACLE_WIDTH / 2 + 1; + } } } private TimeAnimator mAnim; + private Vibrator mVibrator; + private AudioManager mAudioManager; + private final AudioAttributes mAudioAttrs = new AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_GAME).build(); private TextView mScoreField; private View mSplash; @@ -158,6 +173,8 @@ public class LLand extends FrameLayout { public LLand(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); setFocusable(true); PARAMS = new Params(getResources()); mTimeOfDay = irand(0, SKIES.length); @@ -198,7 +215,15 @@ public class LLand extends FrameLayout { final float hsv[] = {0, 0, 0}; - private void reset() { + private void thump() { + if (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) { + // No interruptions. Not even game haptics. + return; + } + mVibrator.vibrate(80, mAudioAttrs); + } + + public void reset() { L("reset"); final Drawable sky = new GradientDrawable( GradientDrawable.Orientation.BOTTOM_TOP, @@ -313,14 +338,16 @@ public class LLand extends FrameLayout { private void setScore(int score) { mScore = score; - if (mScoreField != null) mScoreField.setText(String.valueOf(score)); + if (mScoreField != null) { + mScoreField.setText(DEBUG_IDDQD ? "??" : String.valueOf(score)); + } } private void addScore(int incr) { setScore(mScore + incr); } - private void start(boolean startPlaying) { + public void start(boolean startPlaying) { L("start(startPlaying=%s)", startPlaying?"true":"false"); if (startPlaying) { mPlaying = true; @@ -352,7 +379,7 @@ public class LLand extends FrameLayout { } } - private void stop() { + public void stop() { if (mAnimating) { mAnim.cancel(); mAnim = null; @@ -417,8 +444,10 @@ public class LLand extends FrameLayout { if (mPlaying && mDroid.below(mHeight)) { if (DEBUG_IDDQD) { poke(); + unpoke(); } else { L("player hit the floor"); + thump(); stop(); } } @@ -429,6 +458,7 @@ public class LLand extends FrameLayout { final Obstacle ob = mObstaclesInPlay.get(j); if (mPlaying && ob.intersects(mDroid) && !DEBUG_IDDQD) { L("player hit an obstacle"); + thump(); stop(); } else if (ob.cleared(mDroid)) { if (ob instanceof Stem) passedBarrier = true; @@ -459,8 +489,9 @@ public class LLand extends FrameLayout { // 3. Time for more obstacles! if (mPlaying && (t - mLastPipeTime) > PARAMS.OBSTACLE_PERIOD) { mLastPipeTime = t; - final int obstacley = (int) (Math.random() - * (mHeight - 2*PARAMS.OBSTACLE_MIN - PARAMS.OBSTACLE_GAP)) + PARAMS.OBSTACLE_MIN; + final int obstacley = + (int)(frand() * (mHeight - 2*PARAMS.OBSTACLE_MIN - PARAMS.OBSTACLE_GAP)) + + PARAMS.OBSTACLE_MIN; final int inset = (PARAMS.OBSTACLE_WIDTH - PARAMS.OBSTACLE_STEM_WIDTH) / 2; final int yinset = PARAMS.OBSTACLE_WIDTH/2; @@ -539,7 +570,7 @@ public class LLand extends FrameLayout { @Override public boolean onTouchEvent(MotionEvent ev) { - if (DEBUG) L("touch: %s", ev); + L("touch: %s", ev); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: poke(); @@ -553,7 +584,7 @@ public class LLand extends FrameLayout { @Override public boolean onTrackballEvent(MotionEvent ev) { - if (DEBUG) L("trackball: %s", ev); + L("trackball: %s", ev); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: poke(); @@ -567,7 +598,7 @@ public class LLand extends FrameLayout { @Override public boolean onKeyDown(int keyCode, KeyEvent ev) { - if (DEBUG) L("keyDown: %d", keyCode); + L("keyDown: %d", keyCode); switch (keyCode) { case KeyEvent.KEYCODE_DPAD_CENTER: case KeyEvent.KEYCODE_DPAD_UP: @@ -582,7 +613,7 @@ public class LLand extends FrameLayout { @Override public boolean onKeyUp(int keyCode, KeyEvent ev) { - if (DEBUG) L("keyDown: %d", keyCode); + L("keyDown: %d", keyCode); switch (keyCode) { case KeyEvent.KEYCODE_DPAD_CENTER: case KeyEvent.KEYCODE_DPAD_UP: @@ -597,7 +628,7 @@ public class LLand extends FrameLayout { @Override public boolean onGenericMotionEvent (MotionEvent ev) { - if (DEBUG) L("generic: %s", ev); + L("generic: %s", ev); return false; } @@ -684,6 +715,10 @@ public class LLand extends FrameLayout { private boolean mBoosting; + private final int[] sColors = new int[] { + 0xFF78C557, + }; + private final float[] sHull = new float[] { 0.3f, 0f, // left antenna 0.7f, 0f, // right antenna @@ -692,7 +727,7 @@ public class LLand extends FrameLayout { 0.6f, 1f, // right foot 0.4f, 1f, // left foot BLUE! 0.08f, 0.75f, // sinistram - 0.08f, 0.33f, // cold shoulder + 0.08f, 0.33f, // cold shoulder }; public final float[] corners = new float[sHull.length]; @@ -701,7 +736,7 @@ public class LLand extends FrameLayout { setBackgroundResource(R.drawable.android); getBackground().setTintMode(PorterDuff.Mode.SRC_ATOP); - getBackground().setTint(0xFF00FF00); + getBackground().setTint(sColors[0]); setOutlineProvider(new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { @@ -822,8 +857,9 @@ public class LLand extends FrameLayout { int cx, cy, r; public Pop(Context context, float h) { super(context, h); - int idx = 2*irand(0, POPS.length/2); + int idx = 3*irand(0, POPS.length/3); setBackgroundResource(POPS[idx]); + setAlpha((float)(POPS[idx+2])/255); setScaleX(frand() < 0.5f ? -1 : 1); mRotate = POPS[idx+1] == 0 ? 0 : (frand() < 0.5f ? -1 : 1); setOutlineProvider(new ViewOutlineProvider() { diff --git a/packages/SystemUI/src/com/android/systemui/egg/LLandActivity.java b/packages/SystemUI/src/com/android/systemui/egg/LLandActivity.java index 88fd952..b9f8106 100644 --- a/packages/SystemUI/src/com/android/systemui/egg/LLandActivity.java +++ b/packages/SystemUI/src/com/android/systemui/egg/LLandActivity.java @@ -24,13 +24,21 @@ import android.widget.TextView; import com.android.systemui.R; public class LLandActivity extends Activity { + LLand mLand; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.lland); - LLand world = (LLand) findViewById(R.id.world); - world.setScoreField((TextView) findViewById(R.id.score)); - world.setSplash(findViewById(R.id.welcome)); - Log.v(LLand.TAG, "focus: " + world.requestFocus()); + mLand = (LLand) findViewById(R.id.world); + mLand.setScoreField((TextView) findViewById(R.id.score)); + mLand.setSplash(findViewById(R.id.welcome)); + //Log.v(LLand.TAG, "focus: " + mLand.requestFocus()); + } + + @Override + public void onPause() { + mLand.stop(); + super.onPause(); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index 80ddd4a..f2ebcf6 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -147,16 +147,15 @@ public class CellularTile extends QSTile<QSTile.SignalState> { } private final NetworkSignalChangedCallback mCallback = new NetworkSignalChangedCallback() { - private boolean mWifiEnabled; - private boolean mWifiConnected; - private boolean mAirplaneModeEnabled; + private final CallbackInfo mInfo = new CallbackInfo(); @Override public void onWifiSignalChanged(boolean enabled, boolean connected, int wifiSignalIconId, boolean activityIn, boolean activityOut, String wifiSignalContentDescriptionId, String description) { - mWifiEnabled = enabled; - mWifiConnected = connected; + mInfo.wifiEnabled = enabled; + mInfo.wifiConnected = connected; + refreshState(mInfo); } @Override @@ -164,28 +163,35 @@ public class CellularTile extends QSTile<QSTile.SignalState> { int mobileSignalIconId, String mobileSignalContentDescriptionId, int dataTypeIconId, boolean activityIn, boolean activityOut, - String dataTypeContentDescriptionId, String description, boolean noSim, + String dataTypeContentDescriptionId, String description, boolean isDataTypeIconWide) { - final CallbackInfo info = new CallbackInfo(); // TODO pool? - info.enabled = enabled; - info.wifiEnabled = mWifiEnabled; - info.wifiConnected = mWifiConnected; - info.airplaneModeEnabled = mAirplaneModeEnabled; - info.mobileSignalIconId = mobileSignalIconId; - info.signalContentDescription = mobileSignalContentDescriptionId; - info.dataTypeIconId = dataTypeIconId; - info.dataContentDescription = dataTypeContentDescriptionId; - info.activityIn = activityIn; - info.activityOut = activityOut; - info.enabledDesc = description; - info.noSim = noSim; - info.isDataTypeIconWide = isDataTypeIconWide; - refreshState(info); + mInfo.enabled = enabled; + mInfo.mobileSignalIconId = mobileSignalIconId; + mInfo.signalContentDescription = mobileSignalContentDescriptionId; + mInfo.dataTypeIconId = dataTypeIconId; + mInfo.dataContentDescription = dataTypeContentDescriptionId; + mInfo.activityIn = activityIn; + mInfo.activityOut = activityOut; + mInfo.enabledDesc = description; + mInfo.isDataTypeIconWide = isDataTypeIconWide; + refreshState(mInfo); + } + + @Override + public void onNoSimVisibleChanged(boolean visible) { + mInfo.noSim = visible; + if (mInfo.noSim) { + // Make sure signal gets cleared out when no sims. + mInfo.mobileSignalIconId = 0; + mInfo.dataTypeIconId = 0; + } + refreshState(mInfo); } @Override public void onAirplaneModeChanged(boolean enabled) { - mAirplaneModeEnabled = enabled; + mInfo.airplaneModeEnabled = enabled; + refreshState(mInfo); } public void onMobileDataEnabled(boolean enabled) { @@ -203,7 +209,8 @@ public class CellularTile extends QSTile<QSTile.SignalState> { @Override public Boolean getToggleState() { return mDataController.isMobileDataSupported() - ? mDataController.isMobileDataEnabled() : null; + ? mDataController.isMobileDataEnabled() + : null; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index bccc753..9744dca 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -85,8 +85,7 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> { @Override protected void handleUpdateState(BooleanState state, Object arg) { - state.visible = mController.isHotspotSupported() && mUsageTracker.isRecentlyUsed() - && !mController.isProvisioningNeeded(); + state.visible = mController.isHotspotSupported() && mUsageTracker.isRecentlyUsed(); state.label = mContext.getString(R.string.quick_settings_hotspot_label); state.value = mController.isHotspotEnabled(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java index c524edc..6bad652 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java @@ -47,6 +47,10 @@ public class UserDetailView extends PseudoGridView { ViewGroupAdapterBridge.link(this, mAdapter); } + public void refreshAdapter() { + mAdapter.refresh(); + } + public static class Adapter extends UserSwitcherController.BaseUserAdapter implements OnClickListener { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java index 4fb1189..5e30622 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -217,11 +217,15 @@ public class WifiTile extends QSTile<QSTile.SignalState> { int mobileSignalIconId, String mobileSignalContentDescriptionId, int dataTypeIconId, boolean activityIn, boolean activityOut, - String dataTypeContentDescriptionId, String description, boolean noSim, + String dataTypeContentDescriptionId, String description, boolean isDataTypeIconWide) { // noop } + public void onNoSimVisibleChanged(boolean noSims) { + // noop + } + @Override public void onAirplaneModeChanged(boolean enabled) { // noop diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 4a16f8d..57ac4b0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -689,6 +689,12 @@ public abstract class BaseStatusBar extends SystemUI implements } } + protected boolean isCurrentProfile(int userId) { + synchronized (mCurrentProfiles) { + return mCurrentProfiles.get(userId) != null; + } + } + @Override public String getCurrentMediaNotificationKey() { return null; @@ -1642,7 +1648,11 @@ public abstract class BaseStatusBar extends SystemUI implements protected void handleVisibleToUserChanged(boolean visibleToUser) { try { if (visibleToUser) { - mBarService.onPanelRevealed(); + // Only stop blinking, vibrating, ringing when the user went into the shade + // manually (SHADE or SHADE_LOCKED). + boolean clearNotificationEffects = + (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED); + mBarService.onPanelRevealed(clearNotificationEffects); } else { mBarService.onPanelHidden(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java index 27da6fd..0faad21 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java @@ -244,6 +244,9 @@ public class NotificationContentView extends FrameLayout { public void notifyContentUpdated() { selectLayout(false /* animate */, true /* force */); + if (mContractedChild != null) { + mContractedWrapper.setDark(mDark, false /* animate */, 0 /* delay */); + } } public boolean isContentExpandable() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationCustomViewWrapper.java index 045be3e..0702d7e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationCustomViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationCustomViewWrapper.java @@ -27,7 +27,6 @@ import com.android.systemui.statusbar.phone.NotificationPanelView; public class NotificationCustomViewWrapper extends NotificationViewWrapper { private final ViewInvertHelper mInvertHelper; - private boolean mDark; protected NotificationCustomViewWrapper(View view) { super(view); @@ -36,13 +35,10 @@ public class NotificationCustomViewWrapper extends NotificationViewWrapper { @Override public void setDark(boolean dark, boolean fade, long delay) { - if (mDark != dark) { - mDark = dark; - if (fade) { - mInvertHelper.fade(dark, delay); - } else { - mInvertHelper.update(dark); - } + if (fade) { + mInvertHelper.fade(dark, delay); + } else { + mInvertHelper.update(dark); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaViewWrapper.java index 8f63a79..953c373 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaViewWrapper.java @@ -24,19 +24,14 @@ import android.view.View; */ public class NotificationMediaViewWrapper extends NotificationTemplateViewWrapper { - private boolean mDark; - protected NotificationMediaViewWrapper(Context ctx, View view) { super(ctx, view); } @Override public void setDark(boolean dark, boolean fade, long delay) { - if (mDark != dark) { - mDark = dark; - // Only update the large icon, because the rest is already inverted. - setPictureGrayscale(dark, fade, delay); - } + // Only update the large icon, because the rest is already inverted. + setPictureGrayscale(dark, fade, delay); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java index 8dc14b0..5b6e1cd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationTemplateViewWrapper.java @@ -51,8 +51,6 @@ public class NotificationTemplateViewWrapper extends NotificationViewWrapper { private final int mIconBackgroundDarkColor; private final Interpolator mLinearOutSlowInInterpolator; - private boolean mDark; - protected NotificationTemplateViewWrapper(Context ctx, View view) { super(view); mIconDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha); @@ -95,26 +93,23 @@ public class NotificationTemplateViewWrapper extends NotificationViewWrapper { @Override public void setDark(boolean dark, boolean fade, long delay) { - if (mDark != dark) { - mDark = dark; - if (mInvertHelper != null) { - if (fade) { - mInvertHelper.fade(dark, delay); - } else { - mInvertHelper.update(dark); - } + if (mInvertHelper != null) { + if (fade) { + mInvertHelper.fade(dark, delay); + } else { + mInvertHelper.update(dark); } - if (mIcon != null) { - if (fade) { - fadeIconColorFilter(mIcon, dark, delay); - fadeIconAlpha(mIcon, dark, delay); - } else { - updateIconColorFilter(mIcon, dark); - updateIconAlpha(mIcon, dark); - } + } + if (mIcon != null) { + if (fade) { + fadeIconColorFilter(mIcon, dark, delay); + fadeIconAlpha(mIcon, dark, delay); + } else { + updateIconColorFilter(mIcon, dark); + updateIconAlpha(mIcon, dark); } - setPictureGrayscale(dark, fade, delay); } + setPictureGrayscale(dark, fade, delay); } protected void setPictureGrayscale(boolean grayscale, boolean fade, long delay) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java index 418c57f..8e50abe 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -17,8 +17,10 @@ package com.android.systemui.statusbar; import android.content.Context; +import android.telephony.SubscriptionInfo; import android.util.AttributeSet; import android.util.Log; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; @@ -29,6 +31,9 @@ import com.android.systemui.R; import com.android.systemui.statusbar.policy.NetworkControllerImpl; import com.android.systemui.statusbar.policy.SecurityController; +import java.util.ArrayList; +import java.util.List; + // Intimately tied to the design of res/layout/signal_cluster_view.xml public class SignalClusterView extends LinearLayout @@ -41,23 +46,24 @@ public class SignalClusterView NetworkControllerImpl mNC; SecurityController mSC; + private boolean mNoSimsVisible = false; private boolean mVpnVisible = false; private boolean mWifiVisible = false; private int mWifiStrengthId = 0; - private boolean mMobileVisible = false; - private int mMobileStrengthId = 0, mMobileTypeId = 0; private boolean mIsAirplaneMode = false; private int mAirplaneIconId = 0; private int mAirplaneContentDescription; - private String mWifiDescription, mMobileDescription, mMobileTypeDescription; - private boolean mIsMobileTypeIconWide; + private String mWifiDescription; + private ArrayList<PhoneState> mPhoneStates = new ArrayList<PhoneState>(); - ViewGroup mWifiGroup, mMobileGroup; - ImageView mVpn, mWifi, mMobile, mMobileType, mAirplane; + ViewGroup mWifiGroup; + ImageView mVpn, mWifi, mAirplane, mNoSims; View mWifiAirplaneSpacer; View mWifiSignalSpacer; + LinearLayout mMobileSignalGroup; private int mWideTypeIconStartPadding; + private int mSecondaryTelephonyPadding; private int mEndPadding; private int mEndPaddingNothingVisible; @@ -90,6 +96,8 @@ public class SignalClusterView super.onFinishInflate(); mWideTypeIconStartPadding = getContext().getResources().getDimensionPixelSize( R.dimen.wide_type_icon_start_padding); + mSecondaryTelephonyPadding = getContext().getResources().getDimensionPixelSize( + R.dimen.secondary_telephony_padding); mEndPadding = getContext().getResources().getDimensionPixelSize( R.dimen.signal_cluster_battery_padding); mEndPaddingNothingVisible = getContext().getResources().getDimensionPixelSize( @@ -103,12 +111,14 @@ public class SignalClusterView mVpn = (ImageView) findViewById(R.id.vpn); mWifiGroup = (ViewGroup) findViewById(R.id.wifi_combo); mWifi = (ImageView) findViewById(R.id.wifi_signal); - mMobileGroup = (ViewGroup) findViewById(R.id.mobile_combo); - mMobile = (ImageView) findViewById(R.id.mobile_signal); - mMobileType = (ImageView) findViewById(R.id.mobile_type); mAirplane = (ImageView) findViewById(R.id.airplane); + mNoSims = (ImageView) findViewById(R.id.no_sims); mWifiAirplaneSpacer = findViewById(R.id.wifi_airplane_spacer); mWifiSignalSpacer = findViewById(R.id.wifi_signal_spacer); + mMobileSignalGroup = (LinearLayout) findViewById(R.id.mobile_signal_group); + for (PhoneState state : mPhoneStates) { + mMobileSignalGroup.addView(state.mMobileGroup); + } apply(); } @@ -118,10 +128,9 @@ public class SignalClusterView mVpn = null; mWifiGroup = null; mWifi = null; - mMobileGroup = null; - mMobile = null; - mMobileType = null; mAirplane = null; + mMobileSignalGroup.removeAllViews(); + mMobileSignalGroup = null; super.onDetachedFromWindow(); } @@ -149,18 +158,56 @@ public class SignalClusterView @Override public void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon, - String contentDescription, String typeContentDescription, boolean isTypeIconWide) { - mMobileVisible = visible; - mMobileStrengthId = strengthIcon; - mMobileTypeId = typeIcon; - mMobileDescription = contentDescription; - mMobileTypeDescription = typeContentDescription; - mIsMobileTypeIconWide = isTypeIconWide; + String contentDescription, String typeContentDescription, boolean isTypeIconWide, + int subId) { + PhoneState state = getOrInflateState(subId); + state.mMobileVisible = visible; + state.mMobileStrengthId = strengthIcon; + state.mMobileTypeId = typeIcon; + state.mMobileDescription = contentDescription; + state.mMobileTypeDescription = typeContentDescription; + state.mIsMobileTypeIconWide = isTypeIconWide; apply(); } @Override + public void setNoSims(boolean show) { + mNoSimsVisible = show; + } + + @Override + public void setSubs(List<SubscriptionInfo> subs) { + // Clear out all old subIds. + mPhoneStates.clear(); + if (mMobileSignalGroup != null) { + mMobileSignalGroup.removeAllViews(); + } + final int n = subs.size(); + for (int i = 0; i < n; i++) { + inflatePhoneState(subs.get(i).getSubscriptionId()); + } + } + + private PhoneState getOrInflateState(int subId) { + for (PhoneState state : mPhoneStates) { + if (state.mSubId == subId) { + return state; + } + } + return inflatePhoneState(subId); + } + + private PhoneState inflatePhoneState(int subId) { + PhoneState state = new PhoneState(subId, mContext); + if (mMobileSignalGroup != null) { + mMobileSignalGroup.addView(state.mMobileGroup); + } + mPhoneStates.add(state); + return state; + } + + @Override public void setIsAirplaneMode(boolean is, int airplaneIconId, int contentDescription) { mIsAirplaneMode = is; mAirplaneIconId = airplaneIconId; @@ -175,8 +222,9 @@ public class SignalClusterView // ignore content description, so populate manually if (mWifiVisible && mWifiGroup != null && mWifiGroup.getContentDescription() != null) event.getText().add(mWifiGroup.getContentDescription()); - if (mMobileVisible && mMobileGroup != null && mMobileGroup.getContentDescription() != null) - event.getText().add(mMobileGroup.getContentDescription()); + for (PhoneState state : mPhoneStates) { + state.populateAccessibilityEvent(event); + } return super.dispatchPopulateAccessibilityEvent(event); } @@ -188,12 +236,13 @@ public class SignalClusterView mWifi.setImageDrawable(null); } - if (mMobile != null) { - mMobile.setImageDrawable(null); - } - - if (mMobileType != null) { - mMobileType.setImageDrawable(null); + for (PhoneState state : mPhoneStates) { + if (state.mMobile != null) { + state.mMobile.setImageDrawable(null); + } + if (state.mMobileType != null) { + state.mMobileType.setImageDrawable(null); + } } if(mAirplane != null) { @@ -227,19 +276,17 @@ public class SignalClusterView (mWifiVisible ? "VISIBLE" : "GONE"), mWifiStrengthId)); - if (mMobileVisible && !mIsAirplaneMode) { - mMobile.setImageResource(mMobileStrengthId); - mMobileType.setImageResource(mMobileTypeId); - mMobileGroup.setContentDescription(mMobileTypeDescription + " " + mMobileDescription); - mMobileGroup.setVisibility(View.VISIBLE); - } else { - mMobileGroup.setVisibility(View.GONE); + boolean anyMobileVisible = false; + for (PhoneState state : mPhoneStates) { + if (state.apply(anyMobileVisible)) { + anyMobileVisible = true; + } } if (mIsAirplaneMode) { mAirplane.setImageResource(mAirplaneIconId); mAirplane.setContentDescription(mAirplaneContentDescription != 0 ? - mContext.getString(mAirplaneContentDescription) : ""); + mContext.getString(mAirplaneContentDescription) : null); mAirplane.setVisibility(View.VISIBLE); } else { mAirplane.setVisibility(View.GONE); @@ -251,23 +298,73 @@ public class SignalClusterView mWifiAirplaneSpacer.setVisibility(View.GONE); } - if (mMobileVisible && mMobileTypeId != 0 && mWifiVisible) { + if ((anyMobileVisible || mNoSimsVisible) && mWifiVisible) { mWifiSignalSpacer.setVisibility(View.VISIBLE); } else { mWifiSignalSpacer.setVisibility(View.GONE); } - mMobile.setPaddingRelative(mIsMobileTypeIconWide ? mWideTypeIconStartPadding : 0, 0, 0, 0); + mNoSims.setVisibility(mNoSimsVisible ? View.VISIBLE : View.GONE); - if (DEBUG) Log.d(TAG, - String.format("mobile: %s sig=%d typ=%d", - (mMobileVisible ? "VISIBLE" : "GONE"), - mMobileStrengthId, mMobileTypeId)); + boolean anythingVisible = mNoSimsVisible || mWifiVisible || mIsAirplaneMode + || anyMobileVisible || mVpnVisible; + setPaddingRelative(0, 0, anythingVisible ? mEndPadding : mEndPaddingNothingVisible, 0); + } - mMobileType.setVisibility(mMobileTypeId != 0 ? View.VISIBLE : View.GONE); + private class PhoneState { + private final int mSubId; + private boolean mMobileVisible = false; + private int mMobileStrengthId = 0, mMobileTypeId = 0; + private boolean mIsMobileTypeIconWide; + private String mMobileDescription, mMobileTypeDescription; + + private ViewGroup mMobileGroup; + private ImageView mMobile, mMobileType; + + public PhoneState(int subId, Context context) { + ViewGroup root = (ViewGroup) LayoutInflater.from(context) + .inflate(R.layout.mobile_signal_group, null); + setViews(root); + mSubId = subId; + } - boolean anythingVisible = mWifiVisible || mIsAirplaneMode || mMobileVisible || mVpnVisible; - setPaddingRelative(0, 0, anythingVisible ? mEndPadding : mEndPaddingNothingVisible, 0); + public void setViews(ViewGroup root) { + mMobileGroup = root; + mMobile = (ImageView) root.findViewById(R.id.mobile_signal); + mMobileType = (ImageView) root.findViewById(R.id.mobile_type); + } + + public boolean apply(boolean isSecondaryIcon) { + if (mMobileVisible && !mIsAirplaneMode) { + mMobile.setImageResource(mMobileStrengthId); + mMobileType.setImageResource(mMobileTypeId); + mMobileGroup.setContentDescription(mMobileTypeDescription + + " " + mMobileDescription); + mMobileGroup.setVisibility(View.VISIBLE); + } else { + mMobileGroup.setVisibility(View.GONE); + } + + // When this isn't next to wifi, give it some extra padding between the signals. + mMobileGroup.setPaddingRelative(isSecondaryIcon ? mSecondaryTelephonyPadding : 0, + 0, 0, 0); + mMobile.setPaddingRelative(mIsMobileTypeIconWide ? mWideTypeIconStartPadding : 0, + 0, 0, 0); + + if (DEBUG) Log.d(TAG, String.format("mobile: %s sig=%d typ=%d", + (mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, mMobileTypeId)); + + mMobileType.setVisibility(mMobileTypeId != 0 ? View.VISIBLE : View.GONE); + + return mMobileVisible; + } + + public void populateAccessibilityEvent(AccessibilityEvent event) { + if (mMobileVisible && mMobileGroup != null + && mMobileGroup.getContentDescription() != null) { + event.getText().add(mMobileGroup.getContentDescription()); + } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java index 3d4a1e0..6b167b4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java @@ -46,9 +46,12 @@ public class DozeParameters { public void dump(PrintWriter pw) { pw.println(" DozeParameters:"); pw.print(" getDisplayStateSupported(): "); pw.println(getDisplayStateSupported()); - pw.print(" getPulseDuration(): "); pw.println(getPulseDuration()); - pw.print(" getPulseInDuration(): "); pw.println(getPulseInDuration()); - pw.print(" getPulseInDelay(): "); pw.println(getPulseInDelay()); + pw.print(" getPulseDuration(pickup=false): "); pw.println(getPulseDuration(false)); + pw.print(" getPulseDuration(pickup=true): "); pw.println(getPulseDuration(true)); + pw.print(" getPulseInDuration(pickup=false): "); pw.println(getPulseInDuration(false)); + pw.print(" getPulseInDuration(pickup=true): "); pw.println(getPulseInDuration(true)); + pw.print(" getPulseInDelay(pickup=false): "); pw.println(getPulseInDelay(false)); + pw.print(" getPulseInDelay(pickup=true): "); pw.println(getPulseInDelay(true)); pw.print(" getPulseInVisibleDuration(): "); pw.println(getPulseVisibleDuration()); pw.print(" getPulseOutDuration(): "); pw.println(getPulseOutDuration()); pw.print(" getPulseOnSigMotion(): "); pw.println(getPulseOnSigMotion()); @@ -60,22 +63,27 @@ public class DozeParameters { pw.print(" getPulseSchedule(): "); pw.println(getPulseSchedule()); pw.print(" getPulseScheduleResets(): "); pw.println(getPulseScheduleResets()); pw.print(" getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold()); + pw.print(" getPickupPerformsProxCheck(): "); pw.println(getPickupPerformsProxCheck()); } public boolean getDisplayStateSupported() { return getBoolean("doze.display.supported", R.bool.doze_display_state_supported); } - public int getPulseDuration() { - return getPulseInDuration() + getPulseVisibleDuration() + getPulseOutDuration(); + public int getPulseDuration(boolean pickup) { + return getPulseInDuration(pickup) + getPulseVisibleDuration() + getPulseOutDuration(); } - public int getPulseInDuration() { - return getInt("doze.pulse.duration.in", R.integer.doze_pulse_duration_in); + public int getPulseInDuration(boolean pickup) { + return pickup + ? getInt("doze.pulse.duration.in.pickup", R.integer.doze_pulse_duration_in_pickup) + : getInt("doze.pulse.duration.in", R.integer.doze_pulse_duration_in); } - public int getPulseInDelay() { - return getInt("doze.pulse.delay.in", R.integer.doze_pulse_delay_in); + public int getPulseInDelay(boolean pickup) { + return pickup + ? getInt("doze.pulse.delay.in.pickup", R.integer.doze_pulse_delay_in_pickup) + : getInt("doze.pulse.delay.in", R.integer.doze_pulse_delay_in); } public int getPulseVisibleDuration() { @@ -106,6 +114,10 @@ public class DozeParameters { return getBoolean("doze.pulse.proxcheck", R.bool.doze_proximity_check_before_pulse); } + public boolean getPickupPerformsProxCheck() { + return getBoolean("doze.pickup.proxcheck", R.bool.doze_pickup_performs_proximity_check); + } + public boolean getPulseOnNotifications() { return getBoolean("doze.pulse.notifications", R.bool.doze_pulse_on_notifications); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java index 022e64e..3394a8d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java @@ -21,10 +21,8 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.NonNull; import android.content.Context; -import android.graphics.Color; import android.os.Handler; import android.util.Log; -import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; @@ -219,11 +217,14 @@ public class DozeScrimController { private final Runnable mPulseIn = new Runnable() { @Override public void run() { - if (DEBUG) Log.d(TAG, "Pulse in, mDozing=" + mDozing); + if (DEBUG) Log.d(TAG, "Pulse in, mDozing=" + mDozing + " mPulseReason=" + + DozeLog.pulseReasonToString(mPulseReason)); if (!mDozing) return; DozeLog.tracePulseStart(mPulseReason); - startScrimAnimation(true /* inFront */, 0f, mDozeParameters.getPulseInDuration(), - mPulseInInterpolator, mDozeParameters.getPulseInDelay(), mPulseInFinished); + final boolean pickup = mPulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP; + startScrimAnimation(true /* inFront */, 0f, mDozeParameters.getPulseInDuration(pickup), + mPulseInInterpolator, mDozeParameters.getPulseInDelay(pickup), + mPulseInFinished); // Signal that the pulse is ready to turn the screen on and draw. pulseStarted(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java index 15f6dc2..7ec84da 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java @@ -60,9 +60,13 @@ public final class NavigationBarTransitions extends BarTransitions { @Override public void transitionTo(int mode, boolean animate) { mRequestedMode = mode; - if (mVertical && (mode == MODE_TRANSLUCENT || mode == MODE_TRANSPARENT)) { + if (mVertical) { // translucent mode not allowed when vertical - mode = MODE_OPAQUE; + if (mode == MODE_TRANSLUCENT || mode == MODE_TRANSPARENT) { + mode = MODE_OPAQUE; + } else if (mode == MODE_LIGHTS_OUT_TRANSPARENT) { + mode = MODE_LIGHTS_OUT; + } } super.transitionTo(mode, animate); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 4fb505e..7a3b5e4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -851,14 +851,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } }); - - // set up the dynamic hide/show of the label - // TODO: uncomment, handle this for the Stack scroller aswell -// ((NotificationRowLayout) mStackScroller) -// .setOnSizeChangedListener(new OnSizeChangedListener() { -// @Override -// public void onSizeChanged(View view, int w, int h, int oldw, int oldh) { -// updateCarrierLabelVisibility(false); } mFlashlightController = new FlashlightController(mContext); @@ -922,7 +914,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, filter.addAction("fake_artwork"); } filter.addAction(ACTION_DEMO); - context.registerReceiver(mBroadcastReceiver, filter); + context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); // listen for USER_SETUP_COMPLETE setting (per-user) resetUserSetupObserver(); @@ -3096,12 +3088,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (DEBUG) Log.v(TAG, "onReceive: " + intent); String action = intent.getAction(); if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { - int flags = CommandQueue.FLAG_EXCLUDE_NONE; - String reason = intent.getStringExtra("reason"); - if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) { - flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL; + if (isCurrentProfile(getSendingUserId())) { + int flags = CommandQueue.FLAG_EXCLUDE_NONE; + String reason = intent.getStringExtra("reason"); + if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) { + flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL; + } + animateCollapsePanels(flags); } - animateCollapsePanels(flags); } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { mScreenOn = false; @@ -3801,6 +3795,16 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, * @param state The {@link StatusBarState} to set. */ public void setBarState(int state) { + // If we're visible and switched to SHADE_LOCKED (the user dragged down + // on the lockscreen), clear notification LED, vibration, ringing. + // Other transitions are covered in handleVisibleToUserChanged(). + if (mVisible && mState != state && state == StatusBarState.SHADE_LOCKED) { + try { + mBarService.clearNotificationEffects(); + } catch (RemoteException e) { + // Ignore. + } + } mState = state; mStatusBarWindowManager.setStatusBarState(state); } @@ -4132,6 +4136,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); private final H mHandler = new H(); + // Keeps the last reported state by fireNotificationLight. + private boolean mNotificationLightOn; + @Override public String toString() { return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]"; @@ -4150,6 +4157,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } public void fireNotificationLight(boolean on) { + mNotificationLightOn = on; for (Callback callback : mCallbacks) { callback.onNotificationLight(on); } @@ -4191,6 +4199,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, return mBatteryController != null && mBatteryController.isPowerSave(); } + @Override + public boolean isNotificationLightOn() { + return mNotificationLightOn; + } + private void handleStartDozing(@NonNull Runnable ready) { if (!mDozing) { mDozing = true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index e4eae38..7cbf13f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -30,7 +30,7 @@ import com.android.systemui.R; public class PhoneStatusBarView extends PanelBar { private static final String TAG = "PhoneStatusBarView"; private static final boolean DEBUG = PhoneStatusBar.DEBUG; - private static final boolean DEBUG_GESTURES = true; + private static final boolean DEBUG_GESTURES = false; PhoneStatusBar mBar; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java index 8ce608c..45a1386 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java @@ -122,7 +122,7 @@ public class QSTileHost implements QSTile.Host { tile.userSwitch(newUserId); } mSecurity.onUserSwitched(newUserId); - mNetwork.getAccessPointController().onUserSwitched(newUserId); + mNetwork.onUserSwitched(newUserId); mObserver.register(); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java index b7c74e3..63fcbc5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java @@ -33,5 +33,6 @@ public class AccessibilityContentDescriptions { R.string.accessibility_wifi_three_bars, R.string.accessibility_wifi_signal_full }; + static final int WIFI_NO_CONNECTION = R.string.accessibility_no_wifi; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java index 63c1100..8f40011 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java @@ -35,6 +35,8 @@ public class HotspotControllerImpl implements HotspotController { private static final String TAG = "HotspotController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private static final String TETHER_ENABLE_PACKAGE = "com.android.settings"; + private static final String TETHER_ENABLE_CLASS = "com.android.settings.EnableWifiTether"; private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); private final Receiver mReceiver = new Receiver(); @@ -91,20 +93,14 @@ public class HotspotControllerImpl implements HotspotController { @Override public void setHotspotEnabled(boolean enabled) { final ContentResolver cr = mContext.getContentResolver(); - // This needs to be kept up to date with Settings (WifiApEnabler.setSoftapEnabled) - // in case it is turned on in settings and off in qs (or vice versa). - // Disable Wifi if enabling tethering. - int wifiState = mWifiManager.getWifiState(); - if (enabled && ((wifiState == WifiManager.WIFI_STATE_ENABLING) || - (wifiState == WifiManager.WIFI_STATE_ENABLED))) { - mWifiManager.setWifiEnabled(false); - Settings.Global.putInt(cr, Settings.Global.WIFI_SAVED_STATE, 1); - } - - mWifiManager.setWifiApEnabled(null, enabled); - - // If needed, restore Wifi on tether disable. - if (!enabled) { + // Call provisioning app which is called when enabling Tethering from Settings + if (enabled) { + Intent intent = new Intent(); + intent.setClassName(TETHER_ENABLE_PACKAGE, TETHER_ENABLE_CLASS); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + } else { + mWifiManager.setWifiApEnabled(null, false); if (Settings.Global.getInt(cr, Settings.Global.WIFI_SAVED_STATE, 0) == 1) { mWifiManager.setWifiEnabled(true); Settings.Global.putInt(cr, Settings.Global.WIFI_SAVED_STATE, 0); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java index 7ee1fc5..1460e5f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java @@ -107,6 +107,7 @@ public class KeyguardUserSwitcher { public void show(boolean animate) { if (mUserSwitcher != null && mUserSwitcherContainer.getVisibility() != View.VISIBLE) { cancelAnimations(); + mAdapter.refresh(); mUserSwitcherContainer.setVisibility(View.VISIBLE); mStatusBarView.setKeyguardUserSwitcherShowing(true, animate); if (animate) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java index 20f0a83..30da9cb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java @@ -33,6 +33,7 @@ import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.os.RemoteException; import android.os.ServiceManager; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.format.DateUtils; import android.text.format.Time; @@ -213,7 +214,8 @@ public class MobileDataControllerImpl implements NetworkController.MobileDataCon private static String getActiveSubscriberId(Context context) { final TelephonyManager tele = TelephonyManager.from(context); - final String actualSubscriberId = tele.getSubscriberId(); + final String actualSubscriberId = tele.getSubscriberId( + SubscriptionManager.getDefaultDataSubId()); return actualSubscriberId; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index b024f58..bcf08ff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -22,6 +22,7 @@ public interface NetworkController { void addNetworkSignalChangedCallback(NetworkSignalChangedCallback cb); void removeNetworkSignalChangedCallback(NetworkSignalChangedCallback cb); void setWifiEnabled(boolean enabled); + void onUserSwitched(int newUserId); AccessPointController getAccessPointController(); MobileDataController getMobileDataController(); @@ -32,8 +33,9 @@ public interface NetworkController { void onMobileDataSignalChanged(boolean enabled, int mobileSignalIconId, String mobileSignalContentDescriptionId, int dataTypeIconId, boolean activityIn, boolean activityOut, - String dataTypeContentDescriptionId, String description, boolean noSim, + String dataTypeContentDescriptionId, String description, boolean isDataTypeIconWide); + void onNoSimVisibleChanged(boolean visible); void onAirplaneModeChanged(boolean enabled); void onMobileDataEnabled(boolean enabled); } @@ -48,7 +50,6 @@ public interface NetworkController { void scanForAccessPoints(); boolean connect(AccessPoint ap); boolean canConfigWifi(); - void onUserSwitched(int newUserId); public interface AccessPointCallback { void onAccessPointsChanged(AccessPoint[] accessPoints); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index f3a04b6..6431ab5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -16,12 +16,19 @@ package com.android.systemui.statusbar.policy; +import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; +import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH; +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; +import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; +import static android.net.NetworkCapabilities.TRANSPORT_WIFI; + import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.net.ConnectivityManager; +import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; @@ -35,12 +42,17 @@ import android.provider.Settings; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SignalStrength; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.text.format.DateFormat; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.IccCardConstants; +import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.cdma.EriInfo; import com.android.internal.util.AsyncChannel; @@ -50,6 +62,9 @@ import com.android.systemui.R; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.BitSet; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -64,9 +79,9 @@ public class NetworkControllerImpl extends BroadcastReceiver static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); // additional diagnostics, but not logspew static final boolean CHATTY = Log.isLoggable(TAG + ".Chat", Log.DEBUG); - // Save the previous states of all SignalController state info. + // Save the previous SignalController.States of all SignalControllers for dumps. static final boolean RECORD_HISTORY = true; - // How many to save, must be a power of 2. + // If RECORD_HISTORY how many to save, must be a power of 2. static final int HISTORY_SIZE = 16; private static final int INET_CONDITION_THRESHOLD = 50; @@ -75,29 +90,42 @@ public class NetworkControllerImpl extends BroadcastReceiver private final TelephonyManager mPhone; private final WifiManager mWifiManager; private final ConnectivityManager mConnectivityManager; + private final SubscriptionManager mSubscriptionManager; private final boolean mHasMobileDataFeature; + private final Config mConfig; // Subcontrollers. @VisibleForTesting final WifiSignalController mWifiSignalController; @VisibleForTesting - final MobileSignalController mMobileSignalController; + final Map<Integer, MobileSignalController> mMobileSignalControllers = + new HashMap<Integer, MobileSignalController>(); + // When no SIMs are around at setup, and one is added later, it seems to default to the first + // SIM for most actions. This may be null if there aren't any SIMs around. + private MobileSignalController mDefaultSignalController; private final AccessPointControllerImpl mAccessPoints; private final MobileDataControllerImpl mMobileDataController; - // bluetooth + // Network types that replace the carrier label if the device does not support mobile data. private boolean mBluetoothTethered = false; + private boolean mEthernetConnected = false; - // data connectivity (regardless of state, can we access the internet?) - // state of inet connection - 0 not connected, 100 connected + // state of inet connection private boolean mConnected = false; - private int mConnectedNetworkType = ConnectivityManager.TYPE_NONE; - private String mConnectedNetworkTypeName; private boolean mInetCondition; // Used for Logging and demo. + // BitSets indicating which network transport types (e.g., TRANSPORT_WIFI, TRANSPORT_MOBILE) are + // connected and validated, respectively. + private final BitSet mConnectedTransports = new BitSet(); + private final BitSet mValidatedTransports = new BitSet(); + // States that don't belong to a subcontroller. private boolean mAirplaneMode = false; + private boolean mHasNoSims; private Locale mLocale = null; + // This list holds our ordering. + private List<SubscriptionInfo> mCurrentSubscriptions + = new ArrayList<SubscriptionInfo>(); // All the callbacks. private ArrayList<EmergencyListener> mEmergencyListeners = new ArrayList<EmergencyListener>(); @@ -106,6 +134,10 @@ public class NetworkControllerImpl extends BroadcastReceiver private ArrayList<SignalCluster> mSignalClusters = new ArrayList<SignalCluster>(); private ArrayList<NetworkSignalChangedCallback> mSignalsChangedCallbacks = new ArrayList<NetworkSignalChangedCallback>(); + private boolean mListening; + + // The current user ID. + private int mCurrentUserId; /** * Construct this controller object and register for updates. @@ -114,18 +146,21 @@ public class NetworkControllerImpl extends BroadcastReceiver this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE), (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE), (WifiManager) context.getSystemService(Context.WIFI_SERVICE), - Config.readConfig(context), new AccessPointControllerImpl(context), - new MobileDataControllerImpl(context)); + SubscriptionManager.from(context), Config.readConfig(context), + new AccessPointControllerImpl(context), new MobileDataControllerImpl(context)); registerListeners(); } @VisibleForTesting NetworkControllerImpl(Context context, ConnectivityManager connectivityManager, - TelephonyManager telephonyManager, WifiManager wifiManager, Config config, + TelephonyManager telephonyManager, WifiManager wifiManager, + SubscriptionManager subManager, Config config, AccessPointControllerImpl accessPointController, MobileDataControllerImpl mobileDataController) { mContext = context; + mConfig = config; + mSubscriptionManager = subManager; mConnectivityManager = connectivityManager; mHasMobileDataFeature = mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); @@ -149,16 +184,17 @@ public class NetworkControllerImpl extends BroadcastReceiver }); mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature, mSignalsChangedCallbacks, mSignalClusters, this); - mMobileSignalController = new MobileSignalController(mContext, config, - mHasMobileDataFeature, mPhone, mSignalsChangedCallbacks, mSignalClusters, this); // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it - updateAirplaneMode(true); + updateAirplaneMode(true /* force callback */); mAccessPoints.setNetworkController(this); } private void registerListeners() { - mMobileSignalController.registerListener(); + for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { + mobileSignalController.registerListener(); + } + mSubscriptionManager.registerOnSubscriptionsChangedListener(mSubscriptionListener); // broadcasts IntentFilter filter = new IntentFilter(); @@ -166,16 +202,25 @@ public class NetworkControllerImpl extends BroadcastReceiver filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); + filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); + filter.addAction(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED); filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE); filter.addAction(ConnectivityManager.INET_CONDITION_ACTION); filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); mContext.registerReceiver(this, filter); + mListening = true; + + updateMobileControllers(); } private void unregisterListeners() { - mMobileSignalController.unregisterListener(); + mListening = false; + for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { + mobileSignalController.unregisterListener(); + } + mSubscriptionManager.unregisterOnSubscriptionsChangedListener(mSubscriptionListener); mContext.unregisterReceiver(this); } @@ -195,7 +240,7 @@ public class NetworkControllerImpl extends BroadcastReceiver public void addEmergencyListener(EmergencyListener listener) { mEmergencyListeners.add(listener); - refreshCarrierLabel(); + listener.setEmergencyCallsOnly(isEmergencyOnly()); } public void addCarrierLabel(CarrierLabelListener listener) { @@ -204,7 +249,7 @@ public class NetworkControllerImpl extends BroadcastReceiver } private void notifyMobileDataEnabled(boolean enabled) { - int length = mSignalsChangedCallbacks.size(); + final int length = mSignalsChangedCallbacks.size(); for (int i = 0; i < length; i++) { mSignalsChangedCallbacks.get(i).onMobileDataEnabled(enabled); } @@ -218,12 +263,39 @@ public class NetworkControllerImpl extends BroadcastReceiver return mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE; } + private MobileSignalController getDataController() { + int dataSubId = SubscriptionManager.getDefaultDataSubId(); + if (dataSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + if (DEBUG) Log.e(TAG, "No data sim selected"); + return mDefaultSignalController; + } + if (mMobileSignalControllers.containsKey(dataSubId)) { + return mMobileSignalControllers.get(dataSubId); + } + Log.e(TAG, "Cannot find controller for data sub: " + dataSubId); + return mDefaultSignalController; + } + public String getMobileNetworkName() { - return mMobileSignalController.mCurrentState.networkName; + MobileSignalController controller = getDataController(); + return controller != null ? controller.getState().networkName : ""; } public boolean isEmergencyOnly() { - return mMobileSignalController.isEmergencyOnly(); + int voiceSubId = SubscriptionManager.getDefaultVoiceSubId(); + if (voiceSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { + if (!mobileSignalController.isEmergencyOnly()) { + return false; + } + } + } + if (mMobileSignalControllers.containsKey(voiceSubId)) { + return mMobileSignalControllers.get(voiceSubId).isEmergencyOnly(); + } + Log.e(TAG, "Cannot find controller for voice sub: " + voiceSubId); + // Something is wrong, better assume we can't make calls... + return true; } /** @@ -232,26 +304,35 @@ public class NetworkControllerImpl extends BroadcastReceiver */ void recalculateEmergency() { final boolean emergencyOnly = isEmergencyOnly(); - - int length = mEmergencyListeners.size(); + final int length = mEmergencyListeners.size(); for (int i = 0; i < length; i++) { mEmergencyListeners.get(i).setEmergencyCallsOnly(emergencyOnly); } + // If the emergency has a chance to change, then so does the carrier + // label. + refreshCarrierLabel(); } public void addSignalCluster(SignalCluster cluster) { mSignalClusters.add(cluster); + cluster.setSubs(mCurrentSubscriptions); cluster.setIsAirplaneMode(mAirplaneMode, TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode); + cluster.setNoSims(mHasNoSims); mWifiSignalController.notifyListeners(); - mMobileSignalController.notifyListeners(); + for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { + mobileSignalController.notifyListeners(); + } } public void addNetworkSignalChangedCallback(NetworkSignalChangedCallback cb) { mSignalsChangedCallbacks.add(cb); cb.onAirplaneModeChanged(mAirplaneMode); + cb.onNoSimVisibleChanged(mHasNoSims); mWifiSignalController.notifyListeners(); - mMobileSignalController.notifyListeners(); + for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { + mobileSignalController.notifyListeners(); + } } public void removeNetworkSignalChangedCallback(NetworkSignalChangedCallback cb) { @@ -277,6 +358,14 @@ public class NetworkControllerImpl extends BroadcastReceiver } @Override + public void onUserSwitched(int newUserId) { + mCurrentUserId = newUserId; + mAccessPoints.onUserSwitched(newUserId); + updateConnectivity(); + refreshCarrierLabel(); + } + + @Override public void onReceive(Context context, Intent intent) { if (CHATTY) { Log.d(TAG, "onReceive: intent=" + intent); @@ -284,7 +373,7 @@ public class NetworkControllerImpl extends BroadcastReceiver final String action = intent.getAction(); if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE) || action.equals(ConnectivityManager.INET_CONDITION_ACTION)) { - updateConnectivity(intent); + updateConnectivity(); refreshCarrierLabel(); } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { refreshLocale(); @@ -293,9 +382,121 @@ public class NetworkControllerImpl extends BroadcastReceiver refreshLocale(); updateAirplaneMode(false); refreshCarrierLabel(); + } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED)) { + // We are using different subs now, we might be able to make calls. + recalculateEmergency(); + } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) { + // Notify every MobileSignalController so they can know whether they are the + // data sim or not. + for (MobileSignalController controller : mMobileSignalControllers.values()) { + controller.handleBroadcast(intent); + } + } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) { + // Might have different subscriptions now. + updateMobileControllers(); + } else { + int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, + SubscriptionManager.INVALID_SUBSCRIPTION_ID); + if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + if (mMobileSignalControllers.containsKey(subId)) { + mMobileSignalControllers.get(subId).handleBroadcast(intent); + } else { + // Can't find this subscription... We must be out of date. + updateMobileControllers(); + } + } else { + // No sub id, must be for the wifi. + mWifiSignalController.handleBroadcast(intent); + } } - mWifiSignalController.handleBroadcast(intent); - mMobileSignalController.handleBroadcast(intent); + } + + private void updateMobileControllers() { + if (!mListening) { + return; + } + List<SubscriptionInfo> subscriptions = mSubscriptionManager.getActiveSubscriptionInfoList(); + // If there have been no relevant changes to any of the subscriptions, we can leave as is. + if (hasCorrectMobileControllers(subscriptions)) { + // Even if the controllers are correct, make sure we have the right no sims state. + // Such as on boot, don't need any controllers, because there are no sims, + // but we still need to update the no sim state. + updateNoSims(); + return; + } + setCurrentSubscriptions(subscriptions); + updateNoSims(); + } + + @VisibleForTesting + protected void updateNoSims() { + boolean hasNoSims = mHasMobileDataFeature && mMobileSignalControllers.size() == 0; + if (hasNoSims != mHasNoSims) { + mHasNoSims = hasNoSims; + notifyListeners(); + } + } + + @VisibleForTesting + void setCurrentSubscriptions(List<SubscriptionInfo> subscriptions) { + Collections.sort(subscriptions, new Comparator<SubscriptionInfo>() { + @Override + public int compare(SubscriptionInfo lhs, SubscriptionInfo rhs) { + return lhs.getSimSlotIndex() == rhs.getSimSlotIndex() + ? lhs.getSubscriptionId() - rhs.getSubscriptionId() + : lhs.getSimSlotIndex() - rhs.getSimSlotIndex(); + } + }); + final int length = mSignalClusters.size(); + for (int i = 0; i < length; i++) { + mSignalClusters.get(i).setSubs(subscriptions); + } + mCurrentSubscriptions = subscriptions; + + HashMap<Integer, MobileSignalController> cachedControllers = + new HashMap<Integer, MobileSignalController>(mMobileSignalControllers); + mMobileSignalControllers.clear(); + final int num = subscriptions.size(); + for (int i = 0; i < num; i++) { + int subId = subscriptions.get(i).getSubscriptionId(); + // If we have a copy of this controller already reuse it, otherwise make a new one. + if (cachedControllers.containsKey(subId)) { + mMobileSignalControllers.put(subId, cachedControllers.get(subId)); + } else { + MobileSignalController controller = new MobileSignalController(mContext, mConfig, + mHasMobileDataFeature, mPhone, mSignalsChangedCallbacks, mSignalClusters, + this, subscriptions.get(i)); + mMobileSignalControllers.put(subId, controller); + if (subscriptions.get(i).getSimSlotIndex() == 0) { + mDefaultSignalController = controller; + } + if (mListening) { + controller.registerListener(); + } + } + } + if (mListening) { + for (Integer key : cachedControllers.keySet()) { + if (cachedControllers.get(key) == mDefaultSignalController) { + mDefaultSignalController = null; + } + cachedControllers.get(key).unregisterListener(); + } + } + } + + private boolean hasCorrectMobileControllers(List<SubscriptionInfo> allSubscriptions) { + if (allSubscriptions == null) { + // If null then the system doesn't know the subscriptions yet, instead just wait + // to update the MobileControllers until it knows the state. + return true; + } + for (SubscriptionInfo info : allSubscriptions) { + if (!mMobileSignalControllers.containsKey(info.getSubscriptionId())) { + return false; + } + } + return true; } private void updateAirplaneMode(boolean force) { @@ -303,85 +504,87 @@ public class NetworkControllerImpl extends BroadcastReceiver Settings.Global.AIRPLANE_MODE_ON, 0) == 1); if (airplaneMode != mAirplaneMode || force) { mAirplaneMode = airplaneMode; - mMobileSignalController.setAirplaneMode(mAirplaneMode); - notifyAirplaneCallbacks(); + for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { + mobileSignalController.setAirplaneMode(mAirplaneMode); + } + notifyListeners(); refreshCarrierLabel(); } } private void refreshLocale() { Locale current = mContext.getResources().getConfiguration().locale; - if (current.equals(mLocale)) { + if (!current.equals(mLocale)) { mLocale = current; notifyAllListeners(); } } /** - * Turns inet condition into a boolean indexing for a specific network. - * returns 0 for bad connectivity on this network. - * returns 1 for good connectivity on this network. + * Forces update of all callbacks on both SignalClusters and + * NetworkSignalChangedCallbacks. */ - private int inetConditionForNetwork(int networkType, boolean inetCondition) { - return (inetCondition && mConnectedNetworkType == networkType) ? 1 : 0; - } - private void notifyAllListeners() { - // Something changed, trigger everything! - notifyAirplaneCallbacks(); - mMobileSignalController.notifyListeners(); + notifyListeners(); + for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { + mobileSignalController.notifyListeners(); + } mWifiSignalController.notifyListeners(); } - private void notifyAirplaneCallbacks() { + /** + * Notifies listeners of changes in state of to the NetworkController, but + * does not notify for any info on SignalControllers, for that call + * notifyAllListeners. + */ + private void notifyListeners() { int length = mSignalClusters.size(); for (int i = 0; i < length; i++) { mSignalClusters.get(i).setIsAirplaneMode(mAirplaneMode, TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode); + mSignalClusters.get(i).setNoSims(mHasNoSims); } - // update QS int signalsChangedLength = mSignalsChangedCallbacks.size(); for (int i = 0; i < signalsChangedLength; i++) { mSignalsChangedCallbacks.get(i).onAirplaneModeChanged(mAirplaneMode); + mSignalsChangedCallbacks.get(i).onNoSimVisibleChanged(mHasNoSims); } } /** * Update the Inet conditions and what network we are connected to. */ - private void updateConnectivity(Intent intent) { - final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo(); - - // Are we connected at all, by any interface? - mConnected = info != null && info.isConnected(); - if (mConnected) { - mConnectedNetworkType = info.getType(); - mConnectedNetworkTypeName = info.getTypeName(); - } else { - mConnectedNetworkType = ConnectivityManager.TYPE_NONE; - mConnectedNetworkTypeName = null; + private void updateConnectivity() { + mConnectedTransports.clear(); + mValidatedTransports.clear(); + for (NetworkCapabilities nc : + mConnectivityManager.getDefaultNetworkCapabilitiesForUser(mCurrentUserId)) { + for (int transportType : nc.getTransportTypes()) { + mConnectedTransports.set(transportType); + if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) { + mValidatedTransports.set(transportType); + } + } } - int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0); - if (CHATTY) { - Log.d(TAG, "updateConnectivity: networkInfo=" + info); - Log.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus); + Log.d(TAG, "updateConnectivity: mConnectedTransports=" + mConnectedTransports); + Log.d(TAG, "updateConnectivity: mValidatedTransports=" + mValidatedTransports); } - mInetCondition = connectionStatus > INET_CONDITION_THRESHOLD; - - if (info != null && info.getType() == ConnectivityManager.TYPE_BLUETOOTH) { - mBluetoothTethered = info.isConnected(); - } else { - mBluetoothTethered = false; - } + mConnected = !mConnectedTransports.isEmpty(); + mInetCondition = !mValidatedTransports.isEmpty(); + mBluetoothTethered = mConnectedTransports.get(TRANSPORT_BLUETOOTH); + mEthernetConnected = mConnectedTransports.get(TRANSPORT_ETHERNET); // We want to update all the icons, all at once, for any condition change - mMobileSignalController.setInetCondition(mInetCondition ? 1 : 0, - inetConditionForNetwork(mMobileSignalController.getNetworkType(), mInetCondition)); + for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { + mobileSignalController.setInetCondition( + mInetCondition ? 1 : 0, + mValidatedTransports.get(mobileSignalController.getTransportType()) ? 1 : 0); + } mWifiSignalController.setInetCondition( - inetConditionForNetwork(mWifiSignalController.getNetworkType(), mInetCondition)); + mValidatedTransports.get(mWifiSignalController.getTransportType()) ? 1 : 0); } /** @@ -391,8 +594,10 @@ public class NetworkControllerImpl extends BroadcastReceiver Context context = mContext; WifiSignalController.WifiState wifiState = mWifiSignalController.getState(); - MobileSignalController.MobileState mobileState = mMobileSignalController.getState(); - String label = mMobileSignalController.getLabel("", mConnected, mHasMobileDataFeature); + String label = ""; + for (MobileSignalController controller : mMobileSignalControllers.values()) { + label = controller.getLabel(label, mConnected, mHasMobileDataFeature); + } // TODO Simplify this ugliness, some of the flows below shouldn't be possible anymore // but stay for the sake of history. @@ -400,13 +605,11 @@ public class NetworkControllerImpl extends BroadcastReceiver label = mContext.getString(R.string.bluetooth_tethered); } - final boolean ethernetConnected = - (mConnectedNetworkType == ConnectivityManager.TYPE_ETHERNET); - if (ethernetConnected && !mHasMobileDataFeature) { + if (mEthernetConnected && !mHasMobileDataFeature) { label = context.getString(R.string.ethernet_label); } - if (mAirplaneMode && (!mobileState.connected && !mobileState.isEmergency)) { + if (mAirplaneMode && !isEmergencyOnly()) { // combined values from connected wifi take precedence over airplane mode if (wifiState.connected && mHasMobileDataFeature) { // Suppress "No internet connection." from mobile if wifi connected. @@ -417,8 +620,8 @@ public class NetworkControllerImpl extends BroadcastReceiver R.string.status_bar_settings_signal_meter_disconnected); } } - } else if (!mobileState.dataConnected && !wifiState.connected && !mBluetoothTethered && - !ethernetConnected && !mHasMobileDataFeature) { + } else if (!isMobileDataConnected() && !wifiState.connected && !mBluetoothTethered && + !mEthernetConnected && !mHasMobileDataFeature) { // Pretty much no connection. label = context.getString(R.string.status_bar_settings_signal_meter_disconnected); } @@ -432,11 +635,14 @@ public class NetworkControllerImpl extends BroadcastReceiver } } + private boolean isMobileDataConnected() { + MobileSignalController controller = getDataController(); + return controller != null ? controller.getState().dataConnected : false; + } + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("NetworkController state:"); - pw.println(String.format(" %s network type %d (%s)", - mConnected ? "CONNECTED" : "DISCONNECTED", - mConnectedNetworkType, mConnectedNetworkTypeName)); + pw.println(" - telephony ------"); pw.print(" hasVoiceCallingFeature()="); pw.println(hasVoiceCallingFeature()); @@ -446,6 +652,10 @@ public class NetworkControllerImpl extends BroadcastReceiver pw.println(mBluetoothTethered); pw.println(" - connectivity ------"); + pw.print(" mConnectedTransports="); + pw.println(mConnectedTransports); + pw.print(" mValidatedTransports="); + pw.println(mValidatedTransports); pw.print(" mInetCondition="); pw.println(mInetCondition); pw.print(" mAirplaneMode="); @@ -453,14 +663,15 @@ public class NetworkControllerImpl extends BroadcastReceiver pw.print(" mLocale="); pw.println(mLocale); - mMobileSignalController.dump(pw); + for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) { + mobileSignalController.dump(pw); + } mWifiSignalController.dump(pw); } private boolean mDemoMode; private int mDemoInetCondition; private WifiSignalController.WifiState mDemoWifiState; - private MobileSignalController.MobileState mDemoMobileState; @Override public void dispatchDemoCommand(String command, Bundle args) { @@ -470,12 +681,16 @@ public class NetworkControllerImpl extends BroadcastReceiver mDemoMode = true; mDemoInetCondition = mInetCondition ? 1 : 0; mDemoWifiState = mWifiSignalController.getState(); - mDemoMobileState = mMobileSignalController.getState(); } else if (mDemoMode && command.equals(COMMAND_EXIT)) { if (DEBUG) Log.d(TAG, "Exiting demo mode"); mDemoMode = false; + // Update what MobileSignalControllers, because they may change + // to set the number of sim slots. + updateMobileControllers(); + for (MobileSignalController controller : mMobileSignalControllers.values()) { + controller.resetLastState(); + } mWifiSignalController.resetLastState(); - mMobileSignalController.resetLastState(); registerListeners(); notifyAllListeners(); refreshCarrierLabel(); @@ -493,7 +708,9 @@ public class NetworkControllerImpl extends BroadcastReceiver if (fully != null) { mDemoInetCondition = Boolean.parseBoolean(fully) ? 1 : 0; mWifiSignalController.setInetCondition(mDemoInetCondition); - mMobileSignalController.setInetCondition(mDemoInetCondition, mDemoInetCondition); + for (MobileSignalController controller : mMobileSignalControllers.values()) { + controller.setInetCondition(mDemoInetCondition, mDemoInetCondition); + } } String wifi = args.getString("wifi"); if (wifi != null) { @@ -507,12 +724,47 @@ public class NetworkControllerImpl extends BroadcastReceiver mDemoWifiState.enabled = show; mWifiSignalController.notifyListeners(); } + String sims = args.getString("sims"); + if (sims != null) { + int num = Integer.parseInt(sims); + List<SubscriptionInfo> subs = new ArrayList<SubscriptionInfo>(); + if (num != mMobileSignalControllers.size()) { + mMobileSignalControllers.clear(); + int start = mSubscriptionManager.getActiveSubscriptionInfoCountMax(); + for (int i = start /* get out of normal index range */; i < start + num; i++) { + SubscriptionInfo info = new SubscriptionInfo(i, "", i, "", "", 0, 0, "", 0, + null, 0, 0, ""); + subs.add(info); + mMobileSignalControllers.put(i, new MobileSignalController(mContext, + mConfig, mHasMobileDataFeature, mPhone, mSignalsChangedCallbacks, + mSignalClusters, this, info)); + } + } + final int n = mSignalClusters.size(); + for (int i = 0; i < n; i++) { + mSignalClusters.get(i).setSubs(subs); + } + } + String nosim = args.getString("nosim"); + if (nosim != null) { + boolean show = nosim.equals("show"); + final int n = mSignalClusters.size(); + for (int i = 0; i < n; i++) { + mSignalClusters.get(i).setNoSims(show); + } + } String mobile = args.getString("mobile"); if (mobile != null) { boolean show = mobile.equals("show"); String datatype = args.getString("datatype"); + String slotString = args.getString("slot"); + int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString); + // Hack to index linearly for easy use. + MobileSignalController controller = mMobileSignalControllers + .values().toArray(new MobileSignalController[0])[slot]; + controller.getState().dataSim = datatype != null; if (datatype != null) { - mDemoMobileState.iconGroup = + controller.getState().iconGroup = datatype.equals("1x") ? TelephonyIcons.ONE_X : datatype.equals("3g") ? TelephonyIcons.THREE_G : datatype.equals("4g") ? TelephonyIcons.FOUR_G : @@ -526,17 +778,25 @@ public class NetworkControllerImpl extends BroadcastReceiver int[][] icons = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH; String level = args.getString("level"); if (level != null) { - mDemoMobileState.level = level.equals("null") ? -1 + controller.getState().level = level.equals("null") ? -1 : Math.min(Integer.parseInt(level), icons[0].length - 1); - mDemoMobileState.connected = mDemoMobileState.level >= 0; + controller.getState().connected = controller.getState().level >= 0; } - mDemoMobileState.enabled = show; - mMobileSignalController.notifyListeners(); + controller.getState().enabled = show; + controller.notifyListeners(); } refreshCarrierLabel(); } } + private final OnSubscriptionsChangedListener mSubscriptionListener = + new OnSubscriptionsChangedListener() { + public void onSubscriptionInfoChanged() { + updateMobileControllers(); + }; + }; + + // TODO: Move to its own file. static class WifiSignalController extends SignalController<WifiSignalController.WifiState, SignalController.IconGroup> { private final WifiManager mWifiManager; @@ -546,8 +806,8 @@ public class NetworkControllerImpl extends BroadcastReceiver public WifiSignalController(Context context, boolean hasMobileData, List<NetworkSignalChangedCallback> signalCallbacks, List<SignalCluster> signalClusters, NetworkControllerImpl networkController) { - super("WifiSignalController", context, ConnectivityManager.TYPE_WIFI, signalCallbacks, - signalClusters, networkController); + super("WifiSignalController", context, NetworkCapabilities.TRANSPORT_WIFI, + signalCallbacks, signalClusters, networkController); mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); mHasMobileData = hasMobileData; Handler handler = new WifiHandler(); @@ -571,20 +831,17 @@ public class NetworkControllerImpl extends BroadcastReceiver } @Override - public WifiState cleanState() { + protected WifiState cleanState() { return new WifiState(); } - /** - * {@inheritDoc} - */ @Override public void notifyListeners() { // only show wifi in the cluster if connected or if wifi-only - boolean wifiEnabled = mCurrentState.enabled + boolean wifiVisible = mCurrentState.enabled && (mCurrentState.connected || !mHasMobileData); - String wifiDesc = wifiEnabled ? mCurrentState.ssid : null; - boolean ssidPresent = wifiEnabled && mCurrentState.ssid != null; + String wifiDesc = wifiVisible ? mCurrentState.ssid : null; + boolean ssidPresent = wifiVisible && mCurrentState.ssid != null; String contentDescription = getStringIfExists(getContentDescription()); int length = mSignalsChangedCallbacks.size(); for (int i = 0; i < length; i++) { @@ -596,10 +853,8 @@ public class NetworkControllerImpl extends BroadcastReceiver int signalClustersLength = mSignalClusters.size(); for (int i = 0; i < signalClustersLength; i++) { - mSignalClusters.get(i).setWifiIndicators( - // only show wifi in the cluster if connected or if wifi-only - mCurrentState.enabled && (mCurrentState.connected || !mHasMobileData), - getCurrentIconId(), contentDescription); + mSignalClusters.get(i).setWifiIndicators(wifiVisible, getCurrentIconId(), + contentDescription); } } @@ -622,7 +877,7 @@ public class NetworkControllerImpl extends BroadcastReceiver ? (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO) : mWifiManager.getConnectionInfo(); if (info != null) { - mCurrentState.ssid = huntForSsid(info); + mCurrentState.ssid = getSsid(info); } else { mCurrentState.ssid = null; } @@ -630,6 +885,7 @@ public class NetworkControllerImpl extends BroadcastReceiver mCurrentState.ssid = null; } } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { + // Default to -200 as its below WifiManager.MIN_RSSI. mCurrentState.rssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200); mCurrentState.level = WifiManager.calculateSignalLevel( mCurrentState.rssi, WifiIcons.WIFI_LEVEL_COUNT); @@ -638,7 +894,7 @@ public class NetworkControllerImpl extends BroadcastReceiver notifyListenersIfNecessary(); } - private String huntForSsid(WifiInfo info) { + private String getSsid(WifiInfo info) { String ssid = info.getSSID(); if (ssid != null) { return ssid; @@ -693,15 +949,15 @@ public class NetworkControllerImpl extends BroadcastReceiver @Override public void copyFrom(State s) { + super.copyFrom(s); WifiState state = (WifiState) s; ssid = state.ssid; - super.copyFrom(s); } @Override protected void toString(StringBuilder builder) { - builder.append("ssid=").append(ssid).append(','); super.toString(builder); + builder.append(',').append("ssid=").append(ssid); } @Override @@ -712,12 +968,17 @@ public class NetworkControllerImpl extends BroadcastReceiver } } + // TODO: Move to its own file. static class MobileSignalController extends SignalController<MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> { private final Config mConfig; private final TelephonyManager mPhone; private final String mNetworkNameDefault; private final String mNetworkNameSeparator; + @VisibleForTesting + final PhoneStateListener mPhoneStateListener; + // Save entire info for logging, we only use the id. + private final SubscriptionInfo mSubscriptionInfo; // @VisibleForDemoMode Map<Integer, MobileIconGroup> mNetworkToIconLookup; @@ -736,11 +997,15 @@ public class NetworkControllerImpl extends BroadcastReceiver // need listener lists anymore. public MobileSignalController(Context context, Config config, boolean hasMobileData, TelephonyManager phone, List<NetworkSignalChangedCallback> signalCallbacks, - List<SignalCluster> signalClusters, NetworkControllerImpl networkController) { - super("MobileSignalController", context, ConnectivityManager.TYPE_MOBILE, - signalCallbacks, signalClusters, networkController); + List<SignalCluster> signalClusters, NetworkControllerImpl networkController, + SubscriptionInfo info) { + super("MobileSignalController(" + info.getSubscriptionId() + ")", context, + NetworkCapabilities.TRANSPORT_CELLULAR, signalCallbacks, signalClusters, + networkController); mConfig = config; mPhone = phone; + mSubscriptionInfo = info; + mPhoneStateListener = new MobilePhoneStateListener(info.getSubscriptionId()); mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator); mNetworkNameDefault = getStringIfExists( com.android.internal.R.string.lockscreen_carrier_default); @@ -750,6 +1015,8 @@ public class NetworkControllerImpl extends BroadcastReceiver mLastState.networkName = mCurrentState.networkName = mNetworkNameDefault; mLastState.enabled = mCurrentState.enabled = hasMobileData; mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons; + // Get initial data sim state. + updateDataSim(); } /** @@ -779,15 +1046,19 @@ public class NetworkControllerImpl extends BroadcastReceiver mobileLabel = mCurrentState.networkName; } } else { - mobileLabel = mContext - .getString(R.string.status_bar_settings_signal_meter_disconnected); + mobileLabel = mContext.getString( + R.string.status_bar_settings_signal_meter_disconnected); } + if (currentLabel.length() != 0) { + currentLabel = currentLabel + mNetworkNameSeparator; + } // Now for things that should only be shown when actually using mobile data. if (isMobileLabel) { - return mobileLabel; + return currentLabel + mobileLabel; } else { - return mCurrentState.dataConnected ? mobileLabel : currentLabel; + return currentLabel + + (mCurrentState.dataConnected ? mobileLabel : currentLabel); } } } @@ -845,7 +1116,7 @@ public class NetworkControllerImpl extends BroadcastReceiver mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G); mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G); - if (!mConfig.showAtLeastThreeGees) { + if (!mConfig.showAtLeast3G) { mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN, TelephonyIcons.UNKNOWN); mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, TelephonyIcons.E); @@ -881,31 +1152,31 @@ public class NetworkControllerImpl extends BroadcastReceiver } } - /** - * {@inheritDoc} - */ @Override public void notifyListeners() { MobileIconGroup icons = getIcons(); String contentDescription = getStringIfExists(getContentDescription()); String dataContentDescription = getStringIfExists(icons.mDataContentDescription); - int qsTypeIcon = icons.mQsDataType[mCurrentState.inetForNetwork]; - int length = mSignalsChangedCallbacks.size(); - for (int i = 0; i < length; i++) { - mSignalsChangedCallbacks.get(i).onMobileDataSignalChanged(mCurrentState.enabled - && !mCurrentState.isEmergency && !mCurrentState.airplaneMode, - getQsCurrentIconId(), contentDescription, - qsTypeIcon, - mCurrentState.dataConnected && mCurrentState.activityIn, - mCurrentState.dataConnected && mCurrentState.activityOut, - dataContentDescription, - mCurrentState.isEmergency ? null : mCurrentState.networkName, - mCurrentState.noSim, - // Only wide if actually showing something. - icons.mIsWide && qsTypeIcon != 0); + // Only send data sim callbacks to QS. + if (mCurrentState.dataSim) { + int qsTypeIcon = mCurrentState.dataConnected ? + icons.mQsDataType[mCurrentState.inetForNetwork] : 0; + int length = mSignalsChangedCallbacks.size(); + for (int i = 0; i < length; i++) { + mSignalsChangedCallbacks.get(i).onMobileDataSignalChanged(mCurrentState.enabled + && !mCurrentState.isEmergency && !mCurrentState.airplaneMode, + getQsCurrentIconId(), contentDescription, + qsTypeIcon, + mCurrentState.dataConnected && mCurrentState.activityIn, + mCurrentState.dataConnected && mCurrentState.activityOut, + dataContentDescription, + mCurrentState.isEmergency ? null : mCurrentState.networkName, + // Only wide if actually showing something. + icons.mIsWide && qsTypeIcon != 0); + } } - boolean showDataIcon = mCurrentState.inetForNetwork != 0 + boolean showDataIcon = mCurrentState.dataConnected && mCurrentState.inetForNetwork != 0 || mCurrentState.iconGroup == TelephonyIcons.ROAMING; int typeIcon = showDataIcon ? icons.mDataType : 0; int signalClustersLength = mSignalClusters.size(); @@ -917,12 +1188,13 @@ public class NetworkControllerImpl extends BroadcastReceiver contentDescription, dataContentDescription, // Only wide if actually showing something. - icons.mIsWide && typeIcon != 0); + icons.mIsWide && typeIcon != 0, + mSubscriptionInfo.getSubscriptionId()); } } @Override - public MobileState cleanState() { + protected MobileState cleanState() { return new MobileState(); } @@ -969,42 +1241,32 @@ public class NetworkControllerImpl extends BroadcastReceiver public void handleBroadcast(Intent intent) { String action = intent.getAction(); - if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) { - String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); - final String lockedReason = - intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON); - updateSimState(stateExtra, lockedReason); - updateTelephony(); - } else if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) { + if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) { updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false), intent.getStringExtra(TelephonyIntents.EXTRA_SPN), intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false), intent.getStringExtra(TelephonyIntents.EXTRA_PLMN)); notifyListenersIfNecessary(); + } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) { + updateDataSim(); } } - /** - * Determines the current sim state, based on a TelephonyIntents.ACTION_SIM_STATE_CHANGED - * broadcast. - */ - private final void updateSimState(String stateExtra, String lockedReason) { - if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) { - mSimState = IccCardConstants.State.ABSENT; - } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) { - mSimState = IccCardConstants.State.READY; - } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) { - if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) { - mSimState = IccCardConstants.State.PIN_REQUIRED; - } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) { - mSimState = IccCardConstants.State.PUK_REQUIRED; - } else { - mSimState = IccCardConstants.State.NETWORK_LOCKED; - } + private void updateDataSim() { + int defaultDataSub = SubscriptionManager.getDefaultDataSubId(); + if (SubscriptionManager.isValidSubId(defaultDataSub)) { + mCurrentState.dataSim = defaultDataSub == mSubscriptionInfo.getSubscriptionId(); } else { - mSimState = IccCardConstants.State.UNKNOWN; + // There doesn't seem to be a data sim selected, however if + // there isn't a MobileSignalController with dataSim set, then + // QS won't get any callbacks and will be blank. Instead + // lets just assume we are the data sim (which will basically + // show one at random) in QS until one is selected. The user + // should pick one soon after, so we shouldn't be in this state + // for long. + mCurrentState.dataSim = true; } - if (DEBUG) Log.d(TAG, "updateSimState: mSimState=" + mSimState); + notifyListenersIfNecessary(); } /** @@ -1057,16 +1319,6 @@ public class NetworkControllerImpl extends BroadcastReceiver } mCurrentState.dataConnected = mCurrentState.connected && mDataState == TelephonyManager.DATA_CONNECTED; - if (!isCdma()) { - if (mSimState == IccCardConstants.State.READY || - mSimState == IccCardConstants.State.UNKNOWN) { - mCurrentState.noSim = false; - } else { - mCurrentState.noSim = true; - // No sim, no data. - mCurrentState.dataConnected = false; - } - } if (isRoaming()) { mCurrentState.iconGroup = TelephonyIcons.ROAMING; @@ -1075,6 +1327,11 @@ public class NetworkControllerImpl extends BroadcastReceiver mCurrentState.isEmergency = isEmergencyOnly(); mNetworkController.recalculateEmergency(); } + // Fill in the network name if we think we have it. + if (mCurrentState.networkName == mNetworkNameDefault && mServiceState != null + && mServiceState.getOperatorAlphaShort() != null) { + mCurrentState.networkName = mServiceState.getOperatorAlphaShort(); + } notifyListenersIfNecessary(); } @@ -1090,17 +1347,22 @@ public class NetworkControllerImpl extends BroadcastReceiver @Override public void dump(PrintWriter pw) { super.dump(pw); + pw.println(" mSubscription=" + mSubscriptionInfo + ","); pw.println(" mServiceState=" + mServiceState + ","); pw.println(" mSignalStrength=" + mSignalStrength + ","); pw.println(" mDataState=" + mDataState + ","); pw.println(" mDataNetType=" + mDataNetType + ","); } - PhoneStateListener mPhoneStateListener = new PhoneStateListener() { + class MobilePhoneStateListener extends PhoneStateListener { + public MobilePhoneStateListener(int subId) { + super(subId); + } + @Override public void onSignalStrengthsChanged(SignalStrength signalStrength) { if (DEBUG) { - Log.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength + + Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength + ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel()))); } mSignalStrength = signalStrength; @@ -1110,7 +1372,7 @@ public class NetworkControllerImpl extends BroadcastReceiver @Override public void onServiceStateChanged(ServiceState state) { if (DEBUG) { - Log.d(TAG, "onServiceStateChanged voiceState=" + state.getVoiceRegState() + Log.d(mTag, "onServiceStateChanged voiceState=" + state.getVoiceRegState() + " dataState=" + state.getDataRegState()); } mServiceState = state; @@ -1120,7 +1382,7 @@ public class NetworkControllerImpl extends BroadcastReceiver @Override public void onDataConnectionStateChanged(int state, int networkType) { if (DEBUG) { - Log.d(TAG, "onDataConnectionStateChanged: state=" + state + Log.d(mTag, "onDataConnectionStateChanged: state=" + state + " type=" + networkType); } mDataState = state; @@ -1131,7 +1393,7 @@ public class NetworkControllerImpl extends BroadcastReceiver @Override public void onDataActivity(int direction) { if (DEBUG) { - Log.d(TAG, "onDataActivity: direction=" + direction); + Log.d(mTag, "onDataActivity: direction=" + direction); } setActivity(direction); } @@ -1158,7 +1420,7 @@ public class NetworkControllerImpl extends BroadcastReceiver static class MobileState extends SignalController.State { String networkName; - boolean noSim; + boolean dataSim; boolean dataConnected; boolean isEmergency; boolean airplaneMode; @@ -1166,32 +1428,33 @@ public class NetworkControllerImpl extends BroadcastReceiver @Override public void copyFrom(State s) { + super.copyFrom(s); MobileState state = (MobileState) s; - noSim = state.noSim; + dataSim = state.dataSim; networkName = state.networkName; dataConnected = state.dataConnected; inetForNetwork = state.inetForNetwork; isEmergency = state.isEmergency; airplaneMode = state.airplaneMode; - super.copyFrom(s); } @Override protected void toString(StringBuilder builder) { - builder.append("noSim=").append(noSim).append(','); + super.toString(builder); + builder.append(','); + builder.append("dataSim=").append(dataSim).append(','); builder.append("networkName=").append(networkName).append(','); builder.append("dataConnected=").append(dataConnected).append(','); builder.append("inetForNetwork=").append(inetForNetwork).append(','); builder.append("isEmergency=").append(isEmergency).append(','); - builder.append("airplaneMode=").append(airplaneMode).append(','); - super.toString(builder); + builder.append("airplaneMode=").append(airplaneMode); } @Override public boolean equals(Object o) { return super.equals(o) && Objects.equals(((MobileState) o).networkName, networkName) - && ((MobileState) o).noSim == noSim + && ((MobileState) o).dataSim == dataSim && ((MobileState) o).dataConnected == dataConnected && ((MobileState) o).isEmergency == isEmergency && ((MobileState) o).airplaneMode == airplaneMode @@ -1208,7 +1471,7 @@ public class NetworkControllerImpl extends BroadcastReceiver protected final String mTag; protected final T mCurrentState; protected final T mLastState; - protected final int mNetworkType; + protected final int mTransportType; protected final Context mContext; // The owner of the SignalController (i.e. NetworkController will maintain the following // lists and call notifyListeners whenever the list has changed to ensure everyone @@ -1225,9 +1488,9 @@ public class NetworkControllerImpl extends BroadcastReceiver public SignalController(String tag, Context context, int type, List<NetworkSignalChangedCallback> signalCallbacks, List<SignalCluster> signalClusters, NetworkControllerImpl networkController) { - mTag = TAG + "::" + tag; + mTag = TAG + "." + tag; mNetworkController = networkController; - mNetworkType = type; + mTransportType = type; mContext = context; mSignalsChangedCallbacks = signalCallbacks; mSignalClusters = signalClusters; @@ -1245,8 +1508,8 @@ public class NetworkControllerImpl extends BroadcastReceiver return mCurrentState; } - public int getNetworkType() { - return mNetworkType; + public int getTransportType() { + return mTransportType; } public void setInetCondition(int inetCondition) { @@ -1254,11 +1517,12 @@ public class NetworkControllerImpl extends BroadcastReceiver notifyListenersIfNecessary(); } - // @VisibleForDemoMode /** * Used at the end of demo mode to clear out any ugly state that it has created. * Since we haven't had any callbacks, then isDirty will not have been triggered, * so we can just take the last good state directly from there. + * + * Used for demo mode. */ void resetLastState() { mCurrentState.copyFrom(mLastState); @@ -1281,7 +1545,7 @@ public class NetworkControllerImpl extends BroadcastReceiver public void saveLastState() { if (RECORD_HISTORY) { - recordLast(); + recordLastState(); } // Updates the current time. mCurrentState.time = System.currentTimeMillis(); @@ -1315,7 +1579,7 @@ public class NetworkControllerImpl extends BroadcastReceiver } /** - * Gets the content description for the signal based on current state of connected and + * Gets the content description id for the signal based on current state of connected and * level. */ public int getContentDescription() { @@ -1326,7 +1590,7 @@ public class NetworkControllerImpl extends BroadcastReceiver } } - protected void notifyListenersIfNecessary() { + public void notifyListenersIfNecessary() { if (isDirty()) { saveLastState(); notifyListeners(); @@ -1349,7 +1613,7 @@ public class NetworkControllerImpl extends BroadcastReceiver * Saves the last state of any changes, so we can log the current * and last value of any state data. */ - protected void recordLast() { + protected void recordLastState() { mHistory[mHistoryIndex++ & (HISTORY_SIZE - 1)].copyFrom(mLastState); } @@ -1381,7 +1645,7 @@ public class NetworkControllerImpl extends BroadcastReceiver /** * Generate a blank T. */ - public abstract T cleanState(); + protected abstract T cleanState(); /* * Holds icons for a given state. Arrays are generally indexed as inet @@ -1490,7 +1754,10 @@ public class NetworkControllerImpl extends BroadcastReceiver void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription); void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon, - String contentDescription, String typeContentDescription, boolean isTypeIconWide); + String contentDescription, String typeContentDescription, boolean isTypeIconWide, + int subId); + void setSubs(List<SubscriptionInfo> subs); + void setNoSims(boolean show); void setIsAirplaneMode(boolean is, int airplaneIcon, int contentDescription); } @@ -1505,7 +1772,7 @@ public class NetworkControllerImpl extends BroadcastReceiver @VisibleForTesting static class Config { - boolean showAtLeastThreeGees = false; + boolean showAtLeast3G = false; boolean alwaysShowCdmaRssi = false; boolean show4gForLte = false; boolean hspaDataDistinguishable; @@ -1514,7 +1781,7 @@ public class NetworkControllerImpl extends BroadcastReceiver Config config = new Config(); Resources res = context.getResources(); - config.showAtLeastThreeGees = res.getBoolean(R.bool.config_showMin3G); + config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G); config.alwaysShowCdmaRssi = res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi); config.show4gForLte = res.getBoolean(R.bool.config_show4GForLTE); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index e5b357a..4ac41a1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -417,18 +417,6 @@ public class UserSwitcherController { } } - public int getSwitchableUsers() { - int result = 0; - ArrayList<UserRecord> users = mController.mUsers; - int N = users.size(); - for (int i = 0; i < N; i++) { - if (users.get(i).info != null) { - result++; - } - } - return result; - } - public Drawable getDrawable(Context context, UserRecord item) { if (item.isAddUser) { return context.getDrawable(R.drawable.ic_add_circle_qs); @@ -436,6 +424,10 @@ public class UserSwitcherController { return UserIcons.getDefaultUserIcon(item.isGuest ? UserHandle.USER_NULL : item.info.id, /* light= */ true); } + + public void refresh() { + mController.refreshUsers(UserHandle.USER_NULL); + } } public static final class UserRecord { @@ -500,6 +492,7 @@ public class UserSwitcherController { } else { v = (UserDetailView) convertView; } + v.refreshAdapter(); return v; } |