@Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
      ContentResolver resolver = getActivity().getContentResolver();

      // We load the added tiles and compare it to the list of available tiles.
      // We only show the tiles that aren't already on the grid.
      String order = Settings.Secure.getString(resolver, Settings.Secure.QS_TILES);

      List<String> savedTiles = Arrays.asList(order.split(","));

      final List<QSTileHolder> tilesList = new ArrayList<QSTileHolder>();
      for (String tile : QSUtils.getAvailableTiles(getActivity())) {
        // Don't count the already added tiles
        if (!savedTiles.contains(tile)) {
          QSTileHolder holder = QSTileHolder.from(getActivity(), tile);
          if (holder != null) {
            tilesList.add(holder);
          }
        }
      }

      final DialogInterface.OnClickListener selectionListener =
          new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
              dialog.dismiss();
              final QSTiles tiles = (QSTiles) getTargetFragment();
              if (tiles != null) {
                tiles.addTile(tilesList.get(which).value);
              }
            }
          };

      Collections.sort(
          tilesList,
          new Comparator<QSTileHolder>() {
            @Override
            public int compare(QSTileHolder lhs, QSTileHolder rhs) {
              return lhs.name.compareTo(rhs.name);
            }
          });

      final QSListAdapter adapter =
          new QSListAdapter(getActivity(), getSystemUIContext(getActivity()), tilesList);
      return new AlertDialog.Builder(getActivity())
          .setTitle(R.string.add_qs)
          .setSingleChoiceItems(adapter, -1, selectionListener)
          .setNegativeButton(R.string.cancel, null)
          .create();
    }
  private void updateAddDeleteState() {
    int activeTiles = mDraggableGridView.getChildCount() - (mDraggingActive ? 2 : 1);
    boolean limitReached = activeTiles >= QSUtils.getAvailableTiles(getActivity()).size();
    int iconResId = mDraggingActive ? R.drawable.ic_menu_delete : R.drawable.ic_menu_add_dark;
    int titleResId =
        mDraggingActive
            ? R.string.qs_action_delete
            : limitReached ? R.string.qs_action_no_more_tiles : R.string.qs_action_add;

    TextView title = (TextView) mAddDeleteTile.findViewById(android.R.id.title);
    ImageView icon = (ImageView) mAddDeleteTile.findViewById(android.R.id.icon);

    title.setText(titleResId);
    title.setEnabled(!limitReached);

    icon.setImageResource(iconResId);
    icon.setEnabled(!limitReached);
  }
  private QSTile<?> createTile(String tileSpec) {
    // Ensure tile is supported on this device
    if (!QSUtils.getAvailableTiles(mContext).contains(tileSpec)) {
      return null;
    }
    if (QSUtils.isDynamicQsTile(tileSpec)) {
      return null;
    }

    switch (tileSpec) {
      case QSConstants.TILE_WIFI:
        return new WifiTile(this);
      case QSConstants.TILE_BLUETOOTH:
        return new BluetoothTile(this);
      case QSConstants.TILE_INVERSION:
        return new ColorInversionTile(this);
      case QSConstants.TILE_CELLULAR:
        return new CellularTile(this);
      case QSConstants.TILE_AIRPLANE:
        return new AirplaneModeTile(this);
      case QSConstants.TILE_ROTATION:
        return new RotationLockTile(this);
      case QSConstants.TILE_FLASHLIGHT:
        return new FlashlightTile(this);
      case QSConstants.TILE_LOCATION:
        return new LocationTile(this);
      case QSConstants.TILE_CAST:
        return new CastTile(this);
      case QSConstants.TILE_HOTSPOT:
        return new HotspotTile(this);
      case QSConstants.TILE_NOTIFICATIONS:
        return new NotificationsTile(this);
      case QSConstants.TILE_DATA:
        return new DataTile(this);
      case QSConstants.TILE_ROAMING:
        return new RoamingTile(this);
      case QSConstants.TILE_DDS:
        return new DdsTile(this);
      case QSConstants.TILE_COMPASS:
        return new CompassTile(this);
      case QSConstants.TILE_APN:
        return new ApnTile(this);
      case QSConstants.TILE_PROFILES:
        return new ProfilesTile(this);
      case QSConstants.TILE_PERFORMANCE:
        return new PerfProfileTile(this);
      case QSConstants.TILE_ADB_NETWORK:
        return new AdbOverNetworkTile(this);
      case QSConstants.TILE_NFC:
        return new NfcTile(this);
      case QSConstants.TILE_LOCKSCREEN:
        return new LockscreenToggleTile(this);
      case QSConstants.TILE_LTE:
        return new LteTile(this);
      case QSConstants.TILE_VISUALIZER:
        return new VisualizerTile(this);
      case QSConstants.TILE_SCREEN_TIMEOUT:
        return new ScreenTimeoutTile(this);
      case QSConstants.TILE_LIVE_DISPLAY:
        return new LiveDisplayTile(this);
      case QSConstants.TILE_USB_TETHER:
        return new UsbTetherTile(this);
      case QSConstants.TILE_HEADS_UP:
        return new HeadsUpTile(this);
      case QSConstants.TILE_AMBIENT_DISPLAY:
        return new AmbientDisplayTile(this);
      case QSConstants.TILE_SYNC:
        return new SyncTile(this);
      default:
        throw new IllegalArgumentException("Bad tile spec: " + tileSpec);
    }
  }