public void run() {
    Scanner in = new Scanner(System.in);

    while (true) {
      String msg;

      try {
        msg = in.nextLine().trim();

        Pattern p = Pattern.compile("^@(\\w+)\\s+(.+)");
        Matcher m = p.matcher(msg);

        if (msg.equals("quit")) {
          this.server.disconnect(this);
          in.close();
          System.exit(0);
        } else if (msg.equals("list")) {
          this.server.list(this);
        } else if (m.find()) {
          String receiverName = m.group(1);
          BaseClient receiver = server.lookup(receiverName);

          if (receiver != null) {
            receiver.receive(this.name, "<private> %s".format(m.group(2)));
          } else {
            this.server.broadcast(this.name, m.group(2));
          }
        } else {
          this.server.broadcast(this.name, msg);
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
  @Override
  public void run() {
    PackageManager pm = baseServer.getContext().getPackageManager();
    // get a list of installed apps.
    Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
    mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
    List<ResolveInfo> resolveInfos = pm.queryIntentActivities(mainIntent, 0);

    int screenDensity = getScreenDensity();
    // create a map of app data from the list of installed apps
    Map<String, Tuple> appDataMap = new TreeMap<String, Tuple>();
    for (ResolveInfo resolveInfo : resolveInfos) {
      String pkgName = resolveInfo.activityInfo.packageName;
      String appName = resolveInfo.loadLabel(pm).toString();
      Drawable drawable = null;
      try {
        Resources resources = pm.getResourcesForApplication(pkgName);
        if (resources != null) {
          int iconId = resolveInfo.getIconResource();
          if (iconId != 0) drawable = resources.getDrawableForDensity(iconId, screenDensity);
        }
        //                if (drawable == null)
        //                    drawable = pm.getApplicationIcon(pkgName);
      } catch (Resources.NotFoundException e) {
        Log.e(
            TAG, "Failed to find application icon for package '" + pkgName + "':" + e.getMessage());
      } catch (PackageManager.NameNotFoundException e) {
        Log.e(
            TAG, "Failed to find application info for package '" + pkgName + "':" + e.getMessage());
      }
      byte[] icon = Utility.drawableToBytes(drawable);
      Tuple tuple = new Tuple(pkgName, appName, icon);

      // add the tuple to the map
      appDataMap.put(pkgName, tuple);
    }

    // build an AppList
    AppsResponse.Builder arBuilder = AppsResponse.newBuilder();
    arBuilder.setType(AppsResponse.AppsResponseType.REFRESH);

    // get Request info
    List<AppInfo> currentApps = appsRequest.getCurrentList();
    for (AppInfo appInfo : currentApps) {
      String pkgName = appInfo.getPkgName();
      // compare the client's current apps to our appDataMap
      if (appDataMap.containsKey(pkgName)) {
        // we have this package installed, check to see if it's different from the client's records
        Tuple tuple = appDataMap.remove(pkgName);
        boolean different = false;

        String appName = appInfo.getAppName();
        byte[] iconHash = null;
        if (appInfo.hasIconHash()) iconHash = appInfo.getIconHash().toByteArray();
        if (!appName.equals(tuple.appName)) {
          different = true;
        } else {
          byte[] tupleIconHash = getIconHash(tuple);
          if (!Arrays.equals(iconHash, tupleIconHash)) {
            different = true;
          }
        }

        if (different) {
          // we have this package installed, but it's different, instruct the client to update it
          arBuilder.addUpdated(buildAppInfo(tuple));
        }
        // otherwise, the package hasn't changed, don't tell the client to do anything to it
      } else {
        // we don't have this package installed, instruct the client to remove it
        arBuilder.addRemoved(pkgName);
      }
    }

    // for any remaining apps, instruct the client to add it
    for (Tuple tuple : appDataMap.values()) {
      arBuilder.addNew(buildAppInfo(tuple));
    }

    // build a Response
    Response.Builder rBuilder = Response.newBuilder();
    rBuilder.setType(Response.ResponseType.APPS);
    // add the AppList to the Response
    rBuilder.setApps(arBuilder);

    baseServer.sendMessage(rBuilder.build());
  }
 public LauncherHandler(BaseServer baseServer) {
   // this BroadcastReceiver requires that the sender has the LAUNCHER_STARTED_PERMISSION
   super(SVMP_BROADCAST_PERMISSION, baseServer, LAUNCHER_STARTED_ACTION);
   this.context = baseServer.getContext();
   packageManager = context.getPackageManager();
 }