Bug: 35857805 Test: mmma frameworks/base/packages/Osu Change-Id: Iadaede1806cfe7bcaf57ed185618a6de4451e321 Merged-In: Ie4ea352e11b10a7c1f8780557554486bc2b4fcef
423 lines
17 KiB
Java
423 lines
17 KiB
Java
package com.android;
|
|
|
|
import android.app.Activity;
|
|
import android.app.AlertDialog;
|
|
import android.app.IntentService;
|
|
import android.app.Notification;
|
|
import android.app.NotificationManager;
|
|
import android.app.PendingIntent;
|
|
import android.app.TaskStackBuilder;
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.content.DialogInterface;
|
|
import android.content.Intent;
|
|
import android.graphics.BitmapFactory;
|
|
import android.graphics.drawable.BitmapDrawable;
|
|
import android.net.wifi.WifiConfiguration;
|
|
import android.net.wifi.WifiInfo;
|
|
import android.net.wifi.WifiManager;
|
|
import android.os.Binder;
|
|
import android.os.Bundle;
|
|
import android.os.IBinder;
|
|
import android.util.Log;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.widget.AdapterView;
|
|
import android.widget.ArrayAdapter;
|
|
import android.widget.ImageView;
|
|
import android.widget.ListView;
|
|
import android.widget.TextView;
|
|
|
|
import com.android.anqp.OSUProvider;
|
|
import com.android.hotspot2.AppBridge;
|
|
import com.android.hotspot2.PasspointMatch;
|
|
import com.android.hotspot2.osu.OSUInfo;
|
|
import com.android.hotspot2.osu.OSUManager;
|
|
|
|
import org.xml.sax.SAXException;
|
|
|
|
import java.io.IOException;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
//import com.android.Osu.R;
|
|
|
|
/**
|
|
* Main activity.
|
|
*/
|
|
public class MainActivity extends Activity {
|
|
private static final int NOTIFICATION_ID = 0; // Used for OSU count
|
|
private static final int NOTIFICATION_MESSAGE_ID = 1; // Used for other messages
|
|
private static final Locale LOCALE = java.util.Locale.getDefault();
|
|
|
|
private static volatile OSUService sOsuService;
|
|
|
|
private ListView osuListView;
|
|
private OsuListAdapter2 osuListAdapter;
|
|
private String message;
|
|
|
|
public MainActivity() {
|
|
|
|
}
|
|
|
|
@Override
|
|
protected void onResume() {
|
|
super.onResume();
|
|
if (message != null) {
|
|
showDialog(message);
|
|
message = null;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
|
|
Intent intent = getIntent();
|
|
Bundle bundle = intent.getExtras();
|
|
|
|
if (bundle == null) { // User interaction
|
|
if (sOsuService == null) {
|
|
Intent serviceIntent = new Intent(this, OSUService.class);
|
|
serviceIntent.putExtra(ACTION_KEY, "dummy-key");
|
|
startService(serviceIntent);
|
|
return;
|
|
}
|
|
|
|
List<OSUInfo> osuInfos = sOsuService.getOsuInfos();
|
|
|
|
setContentView(R.layout.activity_main);
|
|
Log.d("osu", "osu count:" + osuInfos.size());
|
|
View noOsuView = findViewById(R.id.no_osu);
|
|
if (osuInfos.size() > 0) {
|
|
noOsuView.setVisibility(View.GONE);
|
|
osuListAdapter = new OsuListAdapter2(this, osuInfos);
|
|
osuListView = (ListView) findViewById(R.id.profile_list);
|
|
osuListView.setAdapter(osuListAdapter);
|
|
osuListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
|
@Override
|
|
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
|
|
OSUInfo osuData = (OSUInfo) adapterView.getAdapter().getItem(position);
|
|
Log.d("osu", "launch osu:" + osuData.getName(LOCALE)
|
|
+ " id:" + osuData.getOsuID());
|
|
sOsuService.selectOsu(osuData.getOsuID());
|
|
finish();
|
|
}
|
|
});
|
|
} else {
|
|
noOsuView.setVisibility(View.VISIBLE);
|
|
}
|
|
} else if (intent.getAction().equals(AppBridge.ACTION_OSU_NOTIFICATION)) {
|
|
if (bundle.containsKey(AppBridge.OSU_COUNT)) {
|
|
showOsuCount(bundle.getInt("osu-count", 0), Collections.<OSUInfo>emptyList());
|
|
} else if (bundle.containsKey(AppBridge.PROV_SUCCESS)) {
|
|
showStatus(bundle.getBoolean(AppBridge.PROV_SUCCESS),
|
|
bundle.getString(AppBridge.SP_NAME),
|
|
bundle.getString(AppBridge.PROV_MESSAGE),
|
|
null);
|
|
} else if (bundle.containsKey(AppBridge.DEAUTH)) {
|
|
showDeauth(bundle.getString(AppBridge.SP_NAME),
|
|
bundle.getBoolean(AppBridge.DEAUTH),
|
|
bundle.getInt(AppBridge.DEAUTH_DELAY),
|
|
bundle.getString(AppBridge.DEAUTH_URL));
|
|
}
|
|
/*
|
|
else if (bundle.containsKey(AppBridge.OSU_INFO)) {
|
|
List<OsuData> osus = printOsuDataList(bundle.getParcelableArray(AppBridge.OSU_INFO));
|
|
showOsuList(osus);
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
|
|
private void showOsuCount(int osuCount, List<OSUInfo> osus) {
|
|
if (osuCount > 0) {
|
|
printOsuDataList(osus);
|
|
sendNotification(osuCount);
|
|
} else {
|
|
cancelNotification();
|
|
}
|
|
finish();
|
|
}
|
|
|
|
private void showStatus(boolean provSuccess, String spName, String provMessage,
|
|
String remoteStatus) {
|
|
if (provSuccess) {
|
|
sendDialogMessage(
|
|
String.format("Credentials for %s was successfully installed", spName));
|
|
} else {
|
|
if (spName != null) {
|
|
if (remoteStatus != null) {
|
|
sendDialogMessage(
|
|
String.format("Failed to install credentials for %s: %s: %s",
|
|
spName, provMessage, remoteStatus));
|
|
} else {
|
|
sendDialogMessage(
|
|
String.format("Failed to install credentials for %s: %s",
|
|
spName, provMessage));
|
|
}
|
|
} else {
|
|
sendDialogMessage(
|
|
String.format("Failed to contact OSU: %s", provMessage));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void showDeauth(String spName, boolean ess, int delay, String url) {
|
|
String delayReadable = getReadableTimeInSeconds(delay);
|
|
if (ess) {
|
|
if (delay > 60) {
|
|
sendDialogMessage(
|
|
String.format("There is an issue connecting to %s [for the next %s]. " +
|
|
"Please visit %s for details", spName, delayReadable, url));
|
|
} else {
|
|
sendDialogMessage(
|
|
String.format("There is an issue connecting to %s. " +
|
|
"Please visit %s for details", spName, url));
|
|
}
|
|
} else {
|
|
sendDialogMessage(
|
|
String.format("There is an issue with the closest Access Point for %s. " +
|
|
"You may wait %s or move to another Access Point to " +
|
|
"regain access. Please visit %s for details.",
|
|
spName, delayReadable, url));
|
|
}
|
|
}
|
|
|
|
private static final String ACTION_KEY = "action";
|
|
|
|
public static class WifiReceiver extends BroadcastReceiver {
|
|
@Override
|
|
public void onReceive(Context c, Intent intent) {
|
|
Log.d(OSUManager.TAG, "OSU App got intent: " + intent.getAction());
|
|
Intent serviceIntent;
|
|
serviceIntent = new Intent(c, OSUService.class);
|
|
serviceIntent.putExtra(ACTION_KEY, intent.getAction());
|
|
serviceIntent.putExtras(intent);
|
|
c.startService(serviceIntent);
|
|
}
|
|
}
|
|
|
|
public static class OSUService extends IntentService {
|
|
private OSUManager mOsuManager;
|
|
private final IBinder mBinder = new Binder();
|
|
|
|
public OSUService() {
|
|
super("OSUService");
|
|
}
|
|
|
|
@Override
|
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
onHandleIntent(intent);
|
|
return START_STICKY;
|
|
}
|
|
|
|
@Override
|
|
public void onCreate() {
|
|
super.onCreate();
|
|
Log.d("YYY", String.format("Service %x running, OSU %x",
|
|
System.identityHashCode(this), System.identityHashCode(mOsuManager)));
|
|
if (mOsuManager == null) {
|
|
mOsuManager = new OSUManager(this);
|
|
}
|
|
sOsuService = this;
|
|
}
|
|
|
|
@Override
|
|
public void onDestroy() {
|
|
super.onDestroy();
|
|
Log.d("YYY", String.format("Service %x killed", System.identityHashCode(this)));
|
|
}
|
|
|
|
@Override
|
|
public IBinder onBind(Intent intent) {
|
|
return mBinder;
|
|
}
|
|
|
|
@Override
|
|
protected void onHandleIntent(Intent intent) {
|
|
Bundle bundle = intent.getExtras();
|
|
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
|
|
Log.d(OSUManager.TAG, "OSU Service got intent: " + intent.getStringExtra(ACTION_KEY));
|
|
switch (intent.getStringExtra(ACTION_KEY)) {
|
|
case WifiManager.SCAN_RESULTS_AVAILABLE_ACTION:
|
|
mOsuManager.pushScanResults(wifiManager.getScanResults());
|
|
break;
|
|
// TODO(b/32883320): use updated intent.
|
|
/*
|
|
case WifiManager.PASSPOINT_WNM_FRAME_RECEIVED_ACTION:
|
|
long bssid = bundle.getLong(WifiManager.EXTRA_PASSPOINT_WNM_BSSID);
|
|
String url = bundle.getString(WifiManager.EXTRA_PASSPOINT_WNM_URL);
|
|
|
|
try {
|
|
if (bundle.containsKey(WifiManager.EXTRA_PASSPOINT_WNM_METHOD)) {
|
|
int method = bundle.getInt(WifiManager.EXTRA_PASSPOINT_WNM_METHOD);
|
|
if (method != OSUProvider.OSUMethod.SoapXml.ordinal()) {
|
|
Log.w(OSUManager.TAG, "Unsupported remediation method: " + method);
|
|
}
|
|
PasspointMatch match = null;
|
|
if (bundle.containsKey(WifiManager.EXTRA_PASSPOINT_WNM_PPOINT_MATCH)) {
|
|
int ordinal =
|
|
bundle.getInt(WifiManager.EXTRA_PASSPOINT_WNM_PPOINT_MATCH);
|
|
if (ordinal >= 0 && ordinal < PasspointMatch.values().length) {
|
|
match = PasspointMatch.values()[ordinal];
|
|
}
|
|
}
|
|
mOsuManager.wnmRemediate(bssid, url, match);
|
|
} else if (bundle.containsKey(WifiManager.EXTRA_PASSPOINT_WNM_ESS)) {
|
|
boolean ess = bundle.getBoolean(WifiManager.EXTRA_PASSPOINT_WNM_ESS);
|
|
int delay = bundle.getInt(WifiManager.EXTRA_PASSPOINT_WNM_DELAY);
|
|
mOsuManager.deauth(bssid, ess, delay, url);
|
|
} else {
|
|
Log.w(OSUManager.TAG, "Unknown WNM event");
|
|
}
|
|
} catch (IOException | SAXException e) {
|
|
Log.w(OSUManager.TAG, "Remediation event failed to parse: " + e);
|
|
}
|
|
break;
|
|
case WifiManager.PASSPOINT_ICON_RECEIVED_ACTION:
|
|
mOsuManager.notifyIconReceived(
|
|
bundle.getLong(WifiManager.EXTRA_PASSPOINT_ICON_BSSID),
|
|
bundle.getString(WifiManager.EXTRA_PASSPOINT_ICON_FILE),
|
|
bundle.getByteArray(WifiManager.EXTRA_PASSPOINT_ICON_DATA));
|
|
break;
|
|
*/
|
|
case WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION:
|
|
mOsuManager.networkConfigChange((WifiConfiguration)
|
|
intent.getParcelableExtra(WifiManager.EXTRA_WIFI_CONFIGURATION));
|
|
break;
|
|
case WifiManager.WIFI_STATE_CHANGED_ACTION:
|
|
int state = bundle.getInt(WifiManager.EXTRA_WIFI_STATE);
|
|
if (state == WifiManager.WIFI_STATE_DISABLED) {
|
|
mOsuManager.wifiStateChange(false);
|
|
} else if (state == WifiManager.WIFI_STATE_ENABLED) {
|
|
mOsuManager.wifiStateChange(true);
|
|
}
|
|
break;
|
|
case WifiManager.NETWORK_STATE_CHANGED_ACTION:
|
|
mOsuManager.networkConnectEvent((WifiInfo)
|
|
intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO));
|
|
break;
|
|
}
|
|
}
|
|
|
|
public List<OSUInfo> getOsuInfos() {
|
|
return mOsuManager.getAvailableOSUs();
|
|
}
|
|
|
|
public void selectOsu(int id) {
|
|
mOsuManager.setOSUSelection(id);
|
|
}
|
|
}
|
|
|
|
private String getReadableTimeInSeconds(int timeSeconds) {
|
|
long hours = TimeUnit.SECONDS.toHours(timeSeconds);
|
|
long minutes = TimeUnit.SECONDS.toMinutes(timeSeconds) - TimeUnit.HOURS.toMinutes(hours);
|
|
long seconds =
|
|
timeSeconds - TimeUnit.HOURS.toSeconds(hours) - TimeUnit.MINUTES.toSeconds(minutes);
|
|
if (hours > 0) {
|
|
return String.format("%02d:%02d:%02d", hours, minutes, seconds);
|
|
} else {
|
|
return String.format("%ds", seconds);
|
|
}
|
|
}
|
|
|
|
private void sendNotification(int count) {
|
|
Notification.Builder builder =
|
|
new Notification.Builder(this)
|
|
.setContentTitle(String.format("%s OSU available", count))
|
|
.setContentText("Choose one to connect")
|
|
.setSmallIcon(android.R.drawable.ic_dialog_info)
|
|
.setAutoCancel(false);
|
|
Intent resultIntent = new Intent(this, MainActivity.class);
|
|
|
|
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
|
|
stackBuilder.addParentStack(MainActivity.class);
|
|
stackBuilder.addNextIntent(resultIntent);
|
|
PendingIntent resultPendingIntent =
|
|
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
builder.setContentIntent(resultPendingIntent);
|
|
NotificationManager notificationManager =
|
|
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
notificationManager.notify(NOTIFICATION_ID, builder.build());
|
|
}
|
|
|
|
private void cancelNotification() {
|
|
NotificationManager notificationManager =
|
|
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
notificationManager.cancel(NOTIFICATION_ID);
|
|
}
|
|
|
|
private void sendDialogMessage(String message) {
|
|
// sendNotificationMessage(message);
|
|
this.message = message;
|
|
}
|
|
|
|
private void showDialog(String message) {
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
builder.setMessage(message)
|
|
.setTitle("OSU");
|
|
builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
|
@Override
|
|
public void onCancel(DialogInterface dialogInterface) {
|
|
dialogInterface.cancel();
|
|
finish();
|
|
}
|
|
});
|
|
AlertDialog dialog = builder.create();
|
|
dialog.show();
|
|
}
|
|
|
|
private void sendNotificationMessage(String title) {
|
|
Notification.Builder builder =
|
|
new Notification.Builder(this)
|
|
.setContentTitle(title)
|
|
.setContentText("Click to dismiss.")
|
|
.setSmallIcon(android.R.drawable.ic_dialog_info)
|
|
.setAutoCancel(true);
|
|
NotificationManager notificationManager =
|
|
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
notificationManager.notify(NOTIFICATION_MESSAGE_ID, builder.build());
|
|
}
|
|
|
|
private static class OsuListAdapter2 extends ArrayAdapter<OSUInfo> {
|
|
private Activity activity;
|
|
|
|
public OsuListAdapter2(Activity activity, List<OSUInfo> osuDataList) {
|
|
super(activity, R.layout.list_item, osuDataList);
|
|
this.activity = activity;
|
|
}
|
|
|
|
@Override
|
|
public View getView(int position, View convertView, ViewGroup parent) {
|
|
View view = convertView;
|
|
if (view == null) {
|
|
view = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent, false);
|
|
}
|
|
OSUInfo osuData = getItem(position);
|
|
TextView osuName = (TextView) view.findViewById(R.id.profile_name);
|
|
osuName.setText(osuData.getName(LOCALE));
|
|
TextView osuDetail = (TextView) view.findViewById(R.id.profile_detail);
|
|
osuDetail.setText(osuData.getServiceDescription(LOCALE));
|
|
ImageView osuIcon = (ImageView) view.findViewById(R.id.profile_logo);
|
|
byte[] iconData = osuData.getIconFileElement().getIconData();
|
|
osuIcon.setImageDrawable(
|
|
new BitmapDrawable(activity.getResources(),
|
|
BitmapFactory.decodeByteArray(iconData, 0, iconData.length)));
|
|
return view;
|
|
}
|
|
}
|
|
|
|
private void printOsuDataList(List<OSUInfo> osuDataList) {
|
|
for (OSUInfo osuData : osuDataList) {
|
|
Log.d("osu", String.format("OSUData:[%s][%s][%d]",
|
|
osuData.getName(LOCALE), osuData.getServiceDescription(LOCALE),
|
|
osuData.getOsuID()));
|
|
}
|
|
}
|
|
|
|
}
|