Initial Contribution
This commit is contained in:
117
src/com/android/settings/AirplaneModeEnabler.java
Normal file
117
src/com/android/settings/AirplaneModeEnabler.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import com.android.internal.telephony.PhoneStateIntentReceiver;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.Preference;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.ServiceState;
|
||||
|
||||
public class AirplaneModeEnabler implements Preference.OnPreferenceChangeListener {
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
private PhoneStateIntentReceiver mPhoneStateReceiver;
|
||||
|
||||
private final CheckBoxPreference mCheckBoxPref;
|
||||
|
||||
private static final int EVENT_SERVICE_STATE_CHANGED = 3;
|
||||
|
||||
private Handler mHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case EVENT_SERVICE_STATE_CHANGED:
|
||||
onAirplaneModeChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public AirplaneModeEnabler(Context context, CheckBoxPreference airplaneModeCheckBoxPreference) {
|
||||
|
||||
mContext = context;
|
||||
mCheckBoxPref = airplaneModeCheckBoxPreference;
|
||||
|
||||
airplaneModeCheckBoxPreference.setPersistent(false);
|
||||
|
||||
mPhoneStateReceiver = new PhoneStateIntentReceiver(mContext, mHandler);
|
||||
mPhoneStateReceiver.notifyServiceState(EVENT_SERVICE_STATE_CHANGED);
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
|
||||
// This is the widget enabled state, not the preference toggled state
|
||||
mCheckBoxPref.setEnabled(true);
|
||||
mCheckBoxPref.setChecked(isAirplaneModeOn());
|
||||
|
||||
mPhoneStateReceiver.registerIntent();
|
||||
mCheckBoxPref.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
mPhoneStateReceiver.unregisterIntent();
|
||||
mCheckBoxPref.setOnPreferenceChangeListener(null);
|
||||
}
|
||||
|
||||
private boolean isAirplaneModeOn() {
|
||||
return Settings.System.getInt(mContext.getContentResolver(),
|
||||
Settings.System.AIRPLANE_MODE_ON, 0) != 0;
|
||||
}
|
||||
|
||||
private void setAirplaneModeOn(boolean enabling) {
|
||||
|
||||
mCheckBoxPref.setEnabled(false);
|
||||
mCheckBoxPref.setSummary(enabling ? R.string.airplane_mode_turning_on
|
||||
: R.string.airplane_mode_turning_off);
|
||||
|
||||
// Change the system setting
|
||||
Settings.System.putInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
|
||||
enabling ? 1 : 0);
|
||||
|
||||
// Post the intent
|
||||
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
|
||||
intent.putExtra("state", enabling);
|
||||
mContext.sendBroadcast(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we've received confirmation that the airplane mode was set.
|
||||
*/
|
||||
private void onAirplaneModeChanged() {
|
||||
ServiceState serviceState = mPhoneStateReceiver.getServiceState();
|
||||
boolean isPhoneOff = serviceState.getState() == ServiceState.STATE_POWER_OFF;
|
||||
mCheckBoxPref.setChecked(isPhoneOff);
|
||||
mCheckBoxPref.setSummary(R.string.airplane_mode_summary);
|
||||
mCheckBoxPref.setEnabled(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when someone clicks on the checkbox preference.
|
||||
*/
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
setAirplaneModeOn((Boolean) newValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
393
src/com/android/settings/ApnEditor.java
Normal file
393
src/com/android/settings/ApnEditor.java
Normal file
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.ContentUris;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemProperties;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.provider.Telephony;
|
||||
import com.android.internal.telephony.TelephonyProperties;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
|
||||
public class ApnEditor extends PreferenceActivity
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
|
||||
private final static String TAG = ApnEditor.class.getSimpleName();
|
||||
|
||||
private final static String SAVED_POS = "pos";
|
||||
|
||||
private static final int MENU_DELETE = Menu.FIRST;
|
||||
private static final int MENU_SAVE = Menu.FIRST + 1;
|
||||
private static final int MENU_CANCEL = Menu.FIRST + 2;
|
||||
|
||||
private static String sNotSet;
|
||||
private EditTextPreference mName;
|
||||
private EditTextPreference mApn;
|
||||
private EditTextPreference mProxy;
|
||||
private EditTextPreference mPort;
|
||||
private EditTextPreference mUser;
|
||||
private EditTextPreference mServer;
|
||||
private EditTextPreference mPassword;
|
||||
private EditTextPreference mMmsc;
|
||||
private EditTextPreference mMcc;
|
||||
private EditTextPreference mMnc;
|
||||
private EditTextPreference mMmsProxy;
|
||||
private EditTextPreference mMmsPort;
|
||||
private EditTextPreference mApnType;
|
||||
|
||||
private Uri mUri;
|
||||
private Cursor mCursor;
|
||||
private boolean mNewApn;
|
||||
private boolean mFirstTime;
|
||||
private Resources mRes;
|
||||
|
||||
/**
|
||||
* Standard projection for the interesting columns of a normal note.
|
||||
*/
|
||||
private static final String[] sProjection = new String[] {
|
||||
Telephony.Carriers._ID, // 0
|
||||
Telephony.Carriers.NAME, // 1
|
||||
Telephony.Carriers.APN, // 2
|
||||
Telephony.Carriers.PROXY, // 3
|
||||
Telephony.Carriers.PORT, // 4
|
||||
Telephony.Carriers.USER, // 5
|
||||
Telephony.Carriers.SERVER, // 6
|
||||
Telephony.Carriers.PASSWORD, // 7
|
||||
Telephony.Carriers.MMSC, // 8
|
||||
Telephony.Carriers.MCC, // 9
|
||||
Telephony.Carriers.MNC, // 10
|
||||
Telephony.Carriers.NUMERIC, // 11
|
||||
Telephony.Carriers.MMSPROXY,// 12
|
||||
Telephony.Carriers.MMSPORT, // 13
|
||||
Telephony.Carriers.TYPE, // 14
|
||||
};
|
||||
|
||||
private static final int ID_INDEX = 0;
|
||||
private static final int NAME_INDEX = 1;
|
||||
private static final int APN_INDEX = 2;
|
||||
private static final int PROXY_INDEX = 3;
|
||||
private static final int PORT_INDEX = 4;
|
||||
private static final int USER_INDEX = 5;
|
||||
private static final int SERVER_INDEX = 6;
|
||||
private static final int PASSWORD_INDEX = 7;
|
||||
private static final int MMSC_INDEX = 8;
|
||||
private static final int MCC_INDEX = 9;
|
||||
private static final int MNC_INDEX = 10;
|
||||
private static final int MMSPROXY_INDEX = 12;
|
||||
private static final int MMSPORT_INDEX = 13;
|
||||
private static final int TYPE_INDEX = 14;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
addPreferencesFromResource(R.xml.apn_editor);
|
||||
|
||||
sNotSet = getResources().getString(R.string.apn_not_set);
|
||||
mName = (EditTextPreference) findPreference("apn_name");
|
||||
mApn = (EditTextPreference) findPreference("apn_apn");
|
||||
mProxy = (EditTextPreference) findPreference("apn_http_proxy");
|
||||
mPort = (EditTextPreference) findPreference("apn_http_port");
|
||||
mUser = (EditTextPreference) findPreference("apn_user");
|
||||
mServer = (EditTextPreference) findPreference("apn_server");
|
||||
mPassword = (EditTextPreference) findPreference("apn_password");
|
||||
mMmsProxy = (EditTextPreference) findPreference("apn_mms_proxy");
|
||||
mMmsPort = (EditTextPreference) findPreference("apn_mms_port");
|
||||
mMmsc = (EditTextPreference) findPreference("apn_mmsc");
|
||||
mMcc = (EditTextPreference) findPreference("apn_mcc");
|
||||
mMnc = (EditTextPreference) findPreference("apn_mnc");
|
||||
mApnType = (EditTextPreference) findPreference("apn_type");
|
||||
|
||||
mRes = getResources();
|
||||
|
||||
final Intent intent = getIntent();
|
||||
final String action = intent.getAction();
|
||||
|
||||
mFirstTime = icicle == null;
|
||||
|
||||
if (action.equals(Intent.ACTION_EDIT)) {
|
||||
mUri = intent.getData();
|
||||
} else if (action.equals(Intent.ACTION_INSERT)) {
|
||||
if (mFirstTime) {
|
||||
mUri = getContentResolver().insert(intent.getData(), new ContentValues());
|
||||
} else {
|
||||
mUri = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI,
|
||||
icicle.getInt(SAVED_POS));
|
||||
}
|
||||
mNewApn = true;
|
||||
// If we were unable to create a new note, then just finish
|
||||
// this activity. A RESULT_CANCELED will be sent back to the
|
||||
// original activity if they requested a result.
|
||||
if (mUri == null) {
|
||||
Log.w(TAG, "Failed to insert new telephony provider into "
|
||||
+ getIntent().getData());
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
// The new entry was created, so assume all will end well and
|
||||
// set the result to be returned.
|
||||
setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));
|
||||
|
||||
} else {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
mCursor = managedQuery(mUri, sProjection, null, null);
|
||||
mCursor.moveToFirst();
|
||||
|
||||
fillUi();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
private void fillUi() {
|
||||
if (mFirstTime) {
|
||||
mFirstTime = false;
|
||||
// Fill in all the values from the db in both text editor and summary
|
||||
mName.setText(mCursor.getString(NAME_INDEX));
|
||||
mApn.setText(mCursor.getString(APN_INDEX));
|
||||
mProxy.setText(mCursor.getString(PROXY_INDEX));
|
||||
mPort.setText(mCursor.getString(PORT_INDEX));
|
||||
mUser.setText(mCursor.getString(USER_INDEX));
|
||||
mServer.setText(mCursor.getString(SERVER_INDEX));
|
||||
mPassword.setText(mCursor.getString(PASSWORD_INDEX));
|
||||
mMmsProxy.setText(mCursor.getString(MMSPROXY_INDEX));
|
||||
mMmsPort.setText(mCursor.getString(MMSPORT_INDEX));
|
||||
mMmsc.setText(mCursor.getString(MMSC_INDEX));
|
||||
mMcc.setText(mCursor.getString(MCC_INDEX));
|
||||
mMnc.setText(mCursor.getString(MNC_INDEX));
|
||||
mApnType.setText(mCursor.getString(TYPE_INDEX));
|
||||
if (mNewApn) {
|
||||
String numeric =
|
||||
SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_NUMERIC);
|
||||
// MCC is first 3 chars and then in 2 - 3 chars of MNC
|
||||
if (numeric != null && numeric.length() > 4) {
|
||||
// Country code
|
||||
String mcc = numeric.substring(0, 3);
|
||||
// Network code
|
||||
String mnc = numeric.substring(3);
|
||||
// Auto populate MNC and MCC for new entries, based on what SIM reports
|
||||
mMcc.setText(mcc);
|
||||
mMnc.setText(mnc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mName.setSummary(checkNull(mName.getText()));
|
||||
mApn.setSummary(checkNull(mApn.getText()));
|
||||
mProxy.setSummary(checkNull(mProxy.getText()));
|
||||
mPort.setSummary(checkNull(mPort.getText()));
|
||||
mUser.setSummary(checkNull(mUser.getText()));
|
||||
mServer.setSummary(checkNull(mServer.getText()));
|
||||
mPassword.setSummary(starify(mPassword.getText()));
|
||||
mMmsProxy.setSummary(checkNull(mMmsProxy.getText()));
|
||||
mMmsPort.setSummary(checkNull(mMmsPort.getText()));
|
||||
mMmsc.setSummary(checkNull(mMmsc.getText()));
|
||||
mMcc.setSummary(checkNull(mMcc.getText()));
|
||||
mMnc.setSummary(checkNull(mMnc.getText()));
|
||||
mApnType.setSummary(checkNull(mApnType.getText()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
// If it's a new APN, then cancel will delete the new entry in onPause
|
||||
if (!mNewApn) {
|
||||
menu.add(0, MENU_DELETE, 0, R.string.menu_delete)
|
||||
.setIcon(android.R.drawable.ic_menu_delete);
|
||||
}
|
||||
menu.add(0, MENU_SAVE, 0, R.string.menu_save)
|
||||
.setIcon(android.R.drawable.ic_menu_save);
|
||||
menu.add(0, MENU_CANCEL, 0, R.string.menu_cancel)
|
||||
.setIcon(android.R.drawable.ic_menu_close_clear_cancel);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENU_DELETE:
|
||||
deleteApn();
|
||||
return true;
|
||||
case MENU_SAVE:
|
||||
if (validateAndSave(false)) {
|
||||
finish();
|
||||
}
|
||||
return true;
|
||||
case MENU_CANCEL:
|
||||
if (mNewApn) {
|
||||
getContentResolver().delete(mUri, null, null);
|
||||
}
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_BACK: {
|
||||
if (validateAndSave(false)) {
|
||||
finish();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle icicle) {
|
||||
super.onSaveInstanceState(icicle);
|
||||
validateAndSave(true);
|
||||
icicle.putInt(SAVED_POS, mCursor.getInt(ID_INDEX));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the key fields' validity and save if valid.
|
||||
* @param force save even if the fields are not valid, if the app is
|
||||
* being suspended
|
||||
* @return true if the data was saved
|
||||
*/
|
||||
private boolean validateAndSave(boolean force) {
|
||||
String name = checkNotSet(mName.getText());
|
||||
String apn = checkNotSet(mApn.getText());
|
||||
String mcc = checkNotSet(mMcc.getText());
|
||||
String mnc = checkNotSet(mMnc.getText());
|
||||
|
||||
String errorMsg = null;
|
||||
if (name.length() < 1) {
|
||||
errorMsg = mRes.getString(R.string.error_name_empty);
|
||||
} else if (apn.length() < 1) {
|
||||
errorMsg = mRes.getString(R.string.error_apn_empty);
|
||||
} else if (mcc.length() != 3) {
|
||||
errorMsg = mRes.getString(R.string.error_mcc_not3);
|
||||
} else if ((mnc.length() & 0xFFFE) != 2) {
|
||||
errorMsg = mRes.getString(R.string.error_mnc_not23);
|
||||
}
|
||||
|
||||
if (errorMsg != null && !force) {
|
||||
showErrorMessage(errorMsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mCursor.moveToFirst()) {
|
||||
Log.w(TAG,
|
||||
"Could not go to the first row in the Cursor when saving data.");
|
||||
return false;
|
||||
}
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
|
||||
values.put(Telephony.Carriers.NAME, name);
|
||||
values.put(Telephony.Carriers.APN, apn);
|
||||
values.put(Telephony.Carriers.PROXY, checkNotSet(mProxy.getText()));
|
||||
values.put(Telephony.Carriers.PORT, checkNotSet(mPort.getText()));
|
||||
values.put(Telephony.Carriers.MMSPROXY, checkNotSet(mMmsProxy.getText()));
|
||||
values.put(Telephony.Carriers.MMSPORT, checkNotSet(mMmsPort.getText()));
|
||||
values.put(Telephony.Carriers.USER, checkNotSet(mUser.getText()));
|
||||
values.put(Telephony.Carriers.SERVER, checkNotSet(mServer.getText()));
|
||||
values.put(Telephony.Carriers.PASSWORD, checkNotSet(mPassword.getText()));
|
||||
values.put(Telephony.Carriers.MMSC, checkNotSet(mMmsc.getText()));
|
||||
values.put(Telephony.Carriers.TYPE, checkNotSet(mApnType.getText()));
|
||||
|
||||
values.put(Telephony.Carriers.MCC, mcc);
|
||||
values.put(Telephony.Carriers.MNC, mnc);
|
||||
|
||||
values.put(Telephony.Carriers.NUMERIC, mcc + mnc);
|
||||
|
||||
getContentResolver().update(mUri, values, null, null);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void showErrorMessage(String message) {
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.error_title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void deleteApn() {
|
||||
getContentResolver().delete(mUri, null, null);
|
||||
finish();
|
||||
}
|
||||
|
||||
private String starify(String value) {
|
||||
if (value == null || value.length() == 0) {
|
||||
return sNotSet;
|
||||
} else {
|
||||
char[] password = new char[value.length()];
|
||||
for (int i = 0; i < password.length; i++) {
|
||||
password[i] = '*';
|
||||
}
|
||||
return new String(password);
|
||||
}
|
||||
}
|
||||
|
||||
private String checkNull(String value) {
|
||||
if (value == null || value.length() == 0) {
|
||||
return sNotSet;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
private String checkNotSet(String value) {
|
||||
if (value == null || value.equals(sNotSet)) {
|
||||
return "";
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
Preference pref = findPreference(key);
|
||||
if (pref != null) {
|
||||
pref.setSummary(checkNull(sharedPreferences.getString(key, "")));
|
||||
}
|
||||
}
|
||||
}
|
||||
111
src/com/android/settings/ApnSettings.java
Normal file
111
src/com/android/settings/ApnSettings.java
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.provider.Telephony;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
public class ApnSettings extends PreferenceActivity {
|
||||
|
||||
public static final String EXTRA_POSITION = "position";
|
||||
|
||||
private static final int ID_INDEX = 0;
|
||||
private static final int NAME_INDEX = 1;
|
||||
private static final int APN_INDEX = 2;
|
||||
|
||||
private static final int MENU_NEW = Menu.FIRST;
|
||||
|
||||
private Cursor mCursor;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
addPreferencesFromResource(R.xml.apn_settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
fillList();
|
||||
}
|
||||
|
||||
private void fillList() {
|
||||
mCursor = managedQuery(Telephony.Carriers.CONTENT_URI, new String[] {
|
||||
"_id", "name", "apn"}, null, Telephony.Carriers.DEFAULT_SORT_ORDER);
|
||||
|
||||
PreferenceCategory apnList = (PreferenceCategory) findPreference("apn_list");
|
||||
apnList.removeAll();
|
||||
|
||||
mCursor.moveToFirst();
|
||||
while (!mCursor.isAfterLast()) {
|
||||
String name = mCursor.getString(NAME_INDEX);
|
||||
String apn = mCursor.getString(APN_INDEX);
|
||||
|
||||
Preference pref = new Preference((Context) this);
|
||||
pref.setKey(mCursor.getString(ID_INDEX));
|
||||
pref.setTitle(name);
|
||||
pref.setSummary(apn);
|
||||
pref.setPersistent(false);
|
||||
apnList.addPreference(pref);
|
||||
mCursor.moveToNext();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
menu.add(0, MENU_NEW, 0,
|
||||
getResources().getString(R.string.menu_new))
|
||||
.setIcon(android.R.drawable.ic_menu_add);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENU_NEW:
|
||||
addNewApn();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void addNewApn() {
|
||||
startActivity(new Intent(Intent.ACTION_INSERT, Telephony.Carriers.CONTENT_URI));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
|
||||
int pos = Integer.parseInt(preference.getKey());
|
||||
Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos);
|
||||
startActivity(new Intent(Intent.ACTION_EDIT, url));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
91
src/com/android/settings/ApplicationSettings.java
Normal file
91
src/com/android/settings/ApplicationSettings.java
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.provider.Settings;
|
||||
|
||||
public class ApplicationSettings extends PreferenceActivity implements
|
||||
DialogInterface.OnClickListener {
|
||||
|
||||
private static final String KEY_TOGGLE_INSTALL_APPLICATIONS = "toggle_install_applications";
|
||||
|
||||
private CheckBoxPreference mToggleAppInstallation;
|
||||
|
||||
private DialogInterface mWarnInstallApps;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
addPreferencesFromResource(R.xml.application_settings);
|
||||
|
||||
mToggleAppInstallation = (CheckBoxPreference) findPreference(KEY_TOGGLE_INSTALL_APPLICATIONS);
|
||||
mToggleAppInstallation.setChecked(isNonMarketAppsAllowed());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
|
||||
if (preference == mToggleAppInstallation) {
|
||||
if (mToggleAppInstallation.isChecked()) {
|
||||
mToggleAppInstallation.setChecked(false);
|
||||
warnAppInstallation();
|
||||
} else {
|
||||
setNonMarketAppsAllowed(false);
|
||||
}
|
||||
}
|
||||
|
||||
return super.onPreferenceTreeClick(preferenceScreen, preference);
|
||||
}
|
||||
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (dialog == mWarnInstallApps && which == DialogInterface.BUTTON1) {
|
||||
setNonMarketAppsAllowed(true);
|
||||
mToggleAppInstallation.setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void setNonMarketAppsAllowed(boolean enabled) {
|
||||
// Change the system setting
|
||||
Settings.System.putInt(getContentResolver(), Settings.System.INSTALL_NON_MARKET_APPS,
|
||||
enabled ? 1 : 0);
|
||||
}
|
||||
|
||||
private boolean isNonMarketAppsAllowed() {
|
||||
return Settings.System.getInt(getContentResolver(),
|
||||
Settings.System.INSTALL_NON_MARKET_APPS, 0) > 0;
|
||||
}
|
||||
|
||||
private void warnAppInstallation() {
|
||||
mWarnInstallApps = new AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.error_title))
|
||||
.setIcon(com.android.internal.R.drawable.ic_dialog_alert)
|
||||
.setMessage(getResources().getString(R.string.install_all_warning))
|
||||
.setPositiveButton(android.R.string.yes, this)
|
||||
.setNegativeButton(android.R.string.no, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
217
src/com/android/settings/BandMode.java
Normal file
217
src/com/android/settings/BandMode.java
Normal file
@@ -0,0 +1,217 @@
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import com.android.internal.telephony.Phone;
|
||||
import com.android.internal.telephony.PhoneFactory;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.os.Handler;
|
||||
import android.os.AsyncResult;
|
||||
import android.util.Log;
|
||||
import android.content.DialogInterface;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.Window;
|
||||
import android.widget.ListView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AdapterView;
|
||||
|
||||
|
||||
/**
|
||||
* Radio Band Mode Selection Class
|
||||
*
|
||||
* It will query baseband about all available band modes and display them
|
||||
* in screen. It will display all six band modes if the query failed.
|
||||
*
|
||||
* After user select one band, it will send the selection to baseband.
|
||||
*
|
||||
* It will alter user the result of select operation and exit, no matter success
|
||||
* or not.
|
||||
*
|
||||
*/
|
||||
public class BandMode extends Activity {
|
||||
private static final String LOG_TAG = "phone";
|
||||
private static final boolean DBG = false;
|
||||
|
||||
private static final int EVENT_BAND_SCAN_COMPLETED = 100;
|
||||
private static final int EVENT_BAND_SELECTION_DONE = 200;
|
||||
|
||||
private static final String[] BAND_NAMES = new String[] {
|
||||
"Automatic",
|
||||
"EURO Band",
|
||||
"USA Band",
|
||||
"JAPAN Band",
|
||||
"AUS Band",
|
||||
"AUS2 Band"
|
||||
};
|
||||
|
||||
private ListView mBandList;
|
||||
private ArrayAdapter mBandListAdapter;
|
||||
private BandListItem mTargetBand = null;
|
||||
private DialogInterface mProgressPanel;
|
||||
|
||||
private Phone mPhone = null;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
||||
|
||||
setContentView(R.layout.band_mode);
|
||||
|
||||
setTitle(getString(R.string.band_mode_title));
|
||||
getWindow().setLayout(WindowManager.LayoutParams.FILL_PARENT,
|
||||
WindowManager.LayoutParams.WRAP_CONTENT);
|
||||
|
||||
mPhone = PhoneFactory.getDefaultPhone();
|
||||
|
||||
mBandList = (ListView) findViewById(R.id.band);
|
||||
mBandListAdapter = new ArrayAdapter<BandListItem>(this,
|
||||
android.R.layout.simple_list_item_1);
|
||||
mBandList.setAdapter(mBandListAdapter);
|
||||
mBandList.setOnItemClickListener(mBandSelectionHandler);
|
||||
|
||||
|
||||
|
||||
loadBandList();
|
||||
}
|
||||
|
||||
private AdapterView.OnItemClickListener mBandSelectionHandler =
|
||||
new AdapterView.OnItemClickListener () {
|
||||
public void onItemClick(AdapterView parent, View v,
|
||||
int position, long id) {
|
||||
|
||||
getWindow().setFeatureInt(
|
||||
Window.FEATURE_INDETERMINATE_PROGRESS,
|
||||
Window.PROGRESS_VISIBILITY_ON);
|
||||
|
||||
mTargetBand = (BandListItem) parent.getAdapter().getItem(position);
|
||||
|
||||
if (DBG) log("Select band : " + mTargetBand.toString());
|
||||
|
||||
Message msg =
|
||||
mHandler.obtainMessage(EVENT_BAND_SELECTION_DONE);
|
||||
mPhone.setBandMode(mTargetBand.getBand(), msg);
|
||||
}
|
||||
};
|
||||
|
||||
private class BandListItem {
|
||||
private int mBandMode = Phone.BM_UNSPECIFIED;
|
||||
|
||||
public BandListItem(int bm) {
|
||||
mBandMode = bm;
|
||||
}
|
||||
|
||||
public int getBand() {
|
||||
return mBandMode;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return BAND_NAMES[mBandMode];
|
||||
}
|
||||
}
|
||||
|
||||
private void loadBandList() {
|
||||
String str = getString(R.string.band_mode_loading);
|
||||
|
||||
if (DBG) log(str);
|
||||
|
||||
|
||||
//ProgressDialog.show(this, null, str, true, true, null);
|
||||
mProgressPanel = new AlertDialog.Builder(this)
|
||||
.setMessage(str)
|
||||
.show();
|
||||
|
||||
Message msg = mHandler.obtainMessage(EVENT_BAND_SCAN_COMPLETED);
|
||||
mPhone.queryAvailableBandMode(msg);
|
||||
|
||||
}
|
||||
|
||||
private void bandListLoaded(AsyncResult result) {
|
||||
if (DBG) log("network list loaded");
|
||||
|
||||
if (mProgressPanel != null) mProgressPanel.dismiss();
|
||||
|
||||
clearList();
|
||||
|
||||
boolean addBandSuccess = false;
|
||||
BandListItem item;
|
||||
|
||||
if (result.result != null) {
|
||||
int bands[] = (int[])result.result;
|
||||
int size = bands[0];
|
||||
|
||||
if (size > 0) {
|
||||
for (int i=1; i<size; i++) {
|
||||
item = new BandListItem(bands[i]);
|
||||
mBandListAdapter.add(item);
|
||||
if (DBG) log("Add " + item.toString());
|
||||
}
|
||||
addBandSuccess = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (addBandSuccess == false) {
|
||||
if (DBG) log("Error in query, add default list");
|
||||
for (int i=0; i<Phone.BM_BOUNDARY; i++) {
|
||||
item = new BandListItem(i);
|
||||
mBandListAdapter.add(item);
|
||||
if (DBG) log("Add default " + item.toString());
|
||||
}
|
||||
}
|
||||
mBandList.requestFocus();
|
||||
}
|
||||
|
||||
private void displayBandSelectionResult(Throwable ex) {
|
||||
String status = getString(R.string.band_mode_set)
|
||||
+" [" + mTargetBand.toString() + "] ";
|
||||
|
||||
if (ex != null) {
|
||||
status = status + getString(R.string.band_mode_failed);
|
||||
} else {
|
||||
status = status + getString(R.string.band_mode_succeeded);
|
||||
}
|
||||
|
||||
mProgressPanel = new AlertDialog.Builder(this)
|
||||
.setMessage(status)
|
||||
.setPositiveButton(android.R.string.ok, null).show();
|
||||
}
|
||||
|
||||
private void clearList() {
|
||||
while(mBandListAdapter.getCount() > 0) {
|
||||
mBandListAdapter.remove(
|
||||
mBandListAdapter.getItem(0));
|
||||
}
|
||||
}
|
||||
|
||||
private void log(String msg) {
|
||||
Log.d(LOG_TAG, "[BandsList] " + msg);
|
||||
}
|
||||
|
||||
private Handler mHandler = new Handler() {
|
||||
public void handleMessage(Message msg) {
|
||||
AsyncResult ar;
|
||||
switch (msg.what) {
|
||||
case EVENT_BAND_SCAN_COMPLETED:
|
||||
ar = (AsyncResult) msg.obj;
|
||||
|
||||
bandListLoaded(ar);
|
||||
break;
|
||||
|
||||
case EVENT_BAND_SELECTION_DONE:
|
||||
ar = (AsyncResult) msg.obj;
|
||||
|
||||
getWindow().setFeatureInt(
|
||||
Window.FEATURE_INDETERMINATE_PROGRESS,
|
||||
Window.PROGRESS_VISIBILITY_OFF);
|
||||
|
||||
displayBandSelectionResult(ar.exception);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
208
src/com/android/settings/BatteryInfo.java
Normal file
208
src/com/android/settings/BatteryInfo.java
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IPowerManager;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemClock;
|
||||
import android.pim.DateUtils;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.app.IBatteryStats;
|
||||
|
||||
public class BatteryInfo extends Activity {
|
||||
private TextView mStatus;
|
||||
private TextView mLevel;
|
||||
private TextView mScale;
|
||||
private TextView mHealth;
|
||||
private TextView mVoltage;
|
||||
private TextView mTemperature;
|
||||
private TextView mTechnology;
|
||||
private TextView mUptime;
|
||||
private TextView mAwakeBattery;
|
||||
private TextView mAwakePlugged;
|
||||
private TextView mScreenOn;
|
||||
private IBatteryStats mBatteryStats;
|
||||
private IPowerManager mScreenStats;
|
||||
|
||||
private static final int EVENT_TICK = 1;
|
||||
|
||||
private Handler mHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case EVENT_TICK:
|
||||
updateBatteryStats();
|
||||
sendEmptyMessageDelayed(EVENT_TICK, 1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Format a number of tenths-units as a decimal string without using a
|
||||
* conversion to float. E.g. 347 -> "34.7"
|
||||
*/
|
||||
private final String tenthsToFixedString(int x) {
|
||||
int tens = x / 10;
|
||||
return new String("" + tens + "." + (x - 10*tens));
|
||||
}
|
||||
|
||||
/**
|
||||
*Listens for intent broadcasts
|
||||
*/
|
||||
private IntentFilter mIntentFilter;
|
||||
|
||||
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
|
||||
int plugType = intent.getIntExtra("plugged", 0);
|
||||
|
||||
mLevel.setText("" + intent.getIntExtra("level", 0));
|
||||
mScale.setText("" + intent.getIntExtra("scale", 0));
|
||||
mVoltage.setText("" + intent.getIntExtra("voltage", 0) + " "
|
||||
+ getString(R.string.battery_info_voltage_units));
|
||||
mTemperature.setText("" + tenthsToFixedString(intent.getIntExtra("temperature", 0))
|
||||
+ getString(R.string.battery_info_temperature_units));
|
||||
mTechnology.setText("" + intent.getStringExtra("technology"));
|
||||
|
||||
int status = intent.getIntExtra("status", BatteryManager.BATTERY_STATUS_UNKNOWN);
|
||||
String statusString;
|
||||
if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
|
||||
statusString = getString(R.string.battery_info_status_charging);
|
||||
if (plugType > 0) {
|
||||
statusString = statusString + " " + getString(
|
||||
(plugType == BatteryManager.BATTERY_PLUGGED_AC)
|
||||
? R.string.battery_info_status_charging_ac
|
||||
: R.string.battery_info_status_charging_usb);
|
||||
}
|
||||
} else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) {
|
||||
statusString = getString(R.string.battery_info_status_discharging);
|
||||
} else if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
|
||||
statusString = getString(R.string.battery_info_status_not_charging);
|
||||
} else if (status == BatteryManager.BATTERY_STATUS_FULL) {
|
||||
statusString = getString(R.string.battery_info_status_full);
|
||||
} else {
|
||||
statusString = getString(R.string.battery_info_status_unknown);
|
||||
}
|
||||
mStatus.setText(statusString);
|
||||
|
||||
int health = intent.getIntExtra("health", BatteryManager.BATTERY_HEALTH_UNKNOWN);
|
||||
String healthString;
|
||||
if (health == BatteryManager.BATTERY_HEALTH_GOOD) {
|
||||
healthString = getString(R.string.battery_info_health_good);
|
||||
} else if (health == BatteryManager.BATTERY_HEALTH_OVERHEAT) {
|
||||
healthString = getString(R.string.battery_info_health_overheat);
|
||||
} else if (health == BatteryManager.BATTERY_HEALTH_DEAD) {
|
||||
healthString = getString(R.string.battery_info_health_dead);
|
||||
} else if (health == BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE) {
|
||||
healthString = getString(R.string.battery_info_health_over_voltage);
|
||||
} else if (health == BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE) {
|
||||
healthString = getString(R.string.battery_info_health_unspecified_failure);
|
||||
} else {
|
||||
healthString = getString(R.string.battery_info_health_unknown);
|
||||
}
|
||||
mHealth.setText(healthString);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
setContentView(R.layout.battery_info);
|
||||
|
||||
// create the IntentFilter that will be used to listen
|
||||
// to battery status broadcasts
|
||||
mIntentFilter = new IntentFilter();
|
||||
mIntentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
mStatus = (TextView)findViewById(R.id.status);
|
||||
mLevel = (TextView)findViewById(R.id.level);
|
||||
mScale = (TextView)findViewById(R.id.scale);
|
||||
mHealth = (TextView)findViewById(R.id.health);
|
||||
mTechnology = (TextView)findViewById(R.id.technology);
|
||||
mVoltage = (TextView)findViewById(R.id.voltage);
|
||||
mTemperature = (TextView)findViewById(R.id.temperature);
|
||||
mUptime = (TextView) findViewById(R.id.uptime);
|
||||
mAwakeBattery = (TextView) findViewById(R.id.awakeBattery);
|
||||
mAwakePlugged = (TextView) findViewById(R.id.awakePlugged);
|
||||
mScreenOn = (TextView) findViewById(R.id.screenOn);
|
||||
|
||||
// Get awake time plugged in and on battery
|
||||
mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
|
||||
mScreenStats = IPowerManager.Stub.asInterface(ServiceManager.getService(POWER_SERVICE));
|
||||
mHandler.sendEmptyMessageDelayed(EVENT_TICK, 1000);
|
||||
|
||||
registerReceiver(mIntentReceiver, mIntentFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mHandler.removeMessages(EVENT_TICK);
|
||||
|
||||
// we are no longer on the screen stop the observers
|
||||
unregisterReceiver(mIntentReceiver);
|
||||
}
|
||||
|
||||
private void updateBatteryStats() {
|
||||
long uptime = SystemClock.elapsedRealtime();
|
||||
mUptime.setText(DateUtils.formatElapsedTime(uptime / 1000));
|
||||
|
||||
if (mBatteryStats != null) {
|
||||
try {
|
||||
long awakeTimeBattery = mBatteryStats.getAwakeTimeBattery();
|
||||
long awakeTimePluggedIn = mBatteryStats.getAwakeTimePlugged();
|
||||
mAwakeBattery.setText(DateUtils.formatElapsedTime(awakeTimeBattery / 1000)
|
||||
+ " (" + (100 * awakeTimeBattery / uptime) + "%)");
|
||||
mAwakePlugged.setText(DateUtils.formatElapsedTime(awakeTimePluggedIn / 1000)
|
||||
+ " (" + (100 * awakeTimePluggedIn / uptime) + "%)");
|
||||
} catch (RemoteException re) {
|
||||
mAwakeBattery.setText("Unknown");
|
||||
mAwakePlugged.setText("Unknown");
|
||||
}
|
||||
}
|
||||
if (mScreenStats != null) {
|
||||
try {
|
||||
long screenOnTime = mScreenStats.getScreenOnTime();
|
||||
mScreenOn.setText(DateUtils.formatElapsedTime(screenOnTime / 1000));
|
||||
} catch (RemoteException re) {
|
||||
mScreenOn.setText("Unknown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
93
src/com/android/settings/BluetoothDataEntry.java
Normal file
93
src/com/android/settings/BluetoothDataEntry.java
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.View.OnKeyListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class BluetoothDataEntry extends Activity implements OnKeyListener {
|
||||
|
||||
private Bundle extras;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
setContentView(R.layout.bluetooth_data_entry);
|
||||
|
||||
mDataLabel = (TextView)findViewById(R.id.dataLabel);
|
||||
mDataEntry = (EditText)findViewById(R.id.dataEntry);
|
||||
mConfirmButton = (Button)findViewById(R.id.confirmButton);
|
||||
mCancelButton = (Button)findViewById(R.id.cancelButton);
|
||||
|
||||
mDataEntry.setOnKeyListener(this);
|
||||
Intent intent = getIntent();
|
||||
String label = null;
|
||||
{
|
||||
String labelExtra = intent.getStringExtra("label");
|
||||
if (labelExtra != null) {
|
||||
label = labelExtra;
|
||||
}
|
||||
}
|
||||
extras = intent.getBundleExtra("extras");
|
||||
if (label != null && label.length() > 0) {
|
||||
mDataLabel.setText(label);
|
||||
}
|
||||
|
||||
mConfirmButton.setOnClickListener(new ConfirmButtonListener());
|
||||
mCancelButton.setOnClickListener(new CancelButtonListener());
|
||||
}
|
||||
|
||||
private class ConfirmButtonListener implements OnClickListener {
|
||||
public void onClick(View v) {
|
||||
activityResult(RESULT_OK, mDataEntry.getText().toString(), extras);
|
||||
}
|
||||
}
|
||||
|
||||
private class CancelButtonListener implements OnClickListener {
|
||||
public void onClick(View v) {
|
||||
activityResult(RESULT_CANCELED, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
protected void activityResult(int result, String data, Bundle extras) {
|
||||
setResult(result, (new Intent()).setAction(data).putExtras(extras));
|
||||
finish();
|
||||
}
|
||||
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER
|
||||
|| keyCode == KeyEvent.KEYCODE_ENTER) {
|
||||
activityResult(RESULT_OK, mDataEntry.getText().toString(), extras);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected TextView mDataLabel;
|
||||
protected EditText mDataEntry;
|
||||
protected Button mConfirmButton;
|
||||
protected Button mCancelButton;
|
||||
}
|
||||
72
src/com/android/settings/BluetoothListItem.java
Normal file
72
src/com/android/settings/BluetoothListItem.java
Normal file
@@ -0,0 +1,72 @@
|
||||
package com.android.settings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.Preference;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class extends Preference to display bluetooth status icons. One
|
||||
* icon specifies the connection/pairing status that is right-aligned.
|
||||
* An optional headset icon can be added to its left as well.
|
||||
*/
|
||||
public class BluetoothListItem extends Preference {
|
||||
|
||||
private boolean mIsHeadset;
|
||||
private int mWeight;
|
||||
|
||||
public BluetoothListItem(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setWidgetLayoutResource(R.layout.preference_widget_btdevice_status);
|
||||
}
|
||||
|
||||
private void updateIcons(View view) {
|
||||
ImageView headsetView = (ImageView) view.findViewById(R.id.device_headset);
|
||||
headsetView.setVisibility(mIsHeadset ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindView(View view) {
|
||||
super.onBindView(view);
|
||||
updateIcons(view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the device is of headset type
|
||||
* @param headset whether or not the headset icon should be shown
|
||||
*/
|
||||
public void setHeadset(boolean headset) {
|
||||
mIsHeadset = headset;
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the weight for ordering by signal strength or importance
|
||||
* @param weight the ordering weight
|
||||
*/
|
||||
public void setWeight(int weight) {
|
||||
mWeight = weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently set ordering weight
|
||||
* @return the current ordering weight
|
||||
*/
|
||||
public int getWeight() {
|
||||
return mWeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Preference another) {
|
||||
int diff = ((BluetoothListItem)another).mWeight - mWeight;
|
||||
// Let the new one be after the old one, if they are the same weight
|
||||
// TODO: Implement a more reliable way to consistently order items of
|
||||
// the same weight
|
||||
if (diff == 0) diff = 1;
|
||||
return diff;
|
||||
}
|
||||
}
|
||||
77
src/com/android/settings/BluetoothPINEntry.java
Normal file
77
src/com/android/settings/BluetoothPINEntry.java
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
public class BluetoothPINEntry extends BluetoothDataEntry {
|
||||
private BluetoothDevice mBluetooth;
|
||||
private String mAddress;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
Intent intent = getIntent();
|
||||
if (!intent.getAction().equals(BluetoothIntent.PAIRING_REQUEST_ACTION))
|
||||
{
|
||||
Log.e(this.getClass().getName(),
|
||||
"Error: this activity may be started only with intent " +
|
||||
BluetoothIntent.PAIRING_REQUEST_ACTION);
|
||||
finish();
|
||||
}
|
||||
|
||||
// Cancel the notification, if any
|
||||
NotificationManager manager = (NotificationManager)
|
||||
getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
manager.cancel(0xb100ceee);
|
||||
|
||||
mAddress = intent.getStringExtra(BluetoothIntent.ADDRESS);
|
||||
|
||||
mBluetooth = (BluetoothDevice)getSystemService(BLUETOOTH_SERVICE);
|
||||
|
||||
String remoteName = mBluetooth.getRemoteName(mAddress);
|
||||
if (remoteName == null) {
|
||||
remoteName = mAddress;
|
||||
}
|
||||
|
||||
mDataLabel.setText(getString(R.string.bluetooth_enter_pin_msg) + remoteName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activityResult(int result, String data, Bundle extras) {
|
||||
switch (result) {
|
||||
case RESULT_OK:
|
||||
byte[] pin = BluetoothDevice.convertPinToBytes(mDataEntry.getText().toString());
|
||||
if (pin == null) {
|
||||
return;
|
||||
}
|
||||
mBluetooth.setPin(mAddress, pin);
|
||||
break;
|
||||
case RESULT_CANCELED:
|
||||
mBluetooth.cancelPin(mAddress);
|
||||
break;
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
80
src/com/android/settings/BluetoothPinRequest.java
Normal file
80
src/com/android/settings/BluetoothPinRequest.java
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
|
||||
/**
|
||||
* This class handles the Bluetooth pairing PIN request from the bluetooth service
|
||||
* It checks if the BluetoothSettings activity is currently visible and lets that
|
||||
* activity handle the request. Otherwise it puts a Notification in the status bar,
|
||||
* which can be clicked to bring up the PIN entry dialog.
|
||||
*/
|
||||
public class BluetoothPinRequest extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent.getAction().equals(BluetoothIntent.PAIRING_REQUEST_ACTION)) {
|
||||
if (BluetoothSettings.isRunning()) {
|
||||
// Let the BluetoothSettings activity handle it
|
||||
return;
|
||||
} else {
|
||||
Resources res = context.getResources();
|
||||
String address = intent.getStringExtra(BluetoothIntent.ADDRESS);
|
||||
Notification pair = new Notification(
|
||||
android.R.drawable.stat_sys_data_bluetooth,
|
||||
res.getString(R.string.bluetooth_notif_ticker),
|
||||
System.currentTimeMillis());
|
||||
|
||||
Intent pinIntent = new Intent();
|
||||
pinIntent.setClass(context, BluetoothPINEntry.class);
|
||||
pinIntent.putExtra(BluetoothIntent.ADDRESS, address);
|
||||
pinIntent.setAction(BluetoothIntent.PAIRING_REQUEST_ACTION);
|
||||
PendingIntent pending = PendingIntent.getActivity(context, 0,
|
||||
pinIntent, PendingIntent.FLAG_ONE_SHOT);
|
||||
|
||||
String name = intent.getStringExtra(BluetoothIntent.NAME);
|
||||
|
||||
if (name == null) {
|
||||
BluetoothDevice bluetooth =
|
||||
(BluetoothDevice)context.getSystemService(Context.BLUETOOTH_SERVICE);
|
||||
name = bluetooth.getRemoteName(address);
|
||||
if (name == null) {
|
||||
name = address;
|
||||
}
|
||||
}
|
||||
|
||||
pair.setLatestEventInfo(context,
|
||||
res.getString(R.string.bluetooth_notif_title),
|
||||
res.getString(R.string.bluetooth_notif_message) + name,
|
||||
pending);
|
||||
|
||||
NotificationManager manager = (NotificationManager)
|
||||
context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
manager.notify(0xb100ceee, pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1035
src/com/android/settings/BluetoothSettings.java
Normal file
1035
src/com/android/settings/BluetoothSettings.java
Normal file
File diff suppressed because it is too large
Load Diff
103
src/com/android/settings/BrightnessPreference.java
Normal file
103
src/com/android/settings/BrightnessPreference.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
import android.os.IHardwareService;
|
||||
import android.os.ServiceManager;
|
||||
import android.preference.SeekBarPreference;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.SettingNotFoundException;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.SeekBar;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class BrightnessPreference extends SeekBarPreference implements
|
||||
SeekBar.OnSeekBarChangeListener {
|
||||
|
||||
private SeekBar mSeekBar;
|
||||
|
||||
private int mOldBrightness;
|
||||
|
||||
// Backlight range is from 0 - 255. Need to make sure that user
|
||||
// doesn't set the backlight to 0 and get stuck
|
||||
private static final int MINIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_DIM + 10;
|
||||
private static final int MAXIMUM_BACKLIGHT = android.os.Power.BRIGHTNESS_ON;
|
||||
|
||||
public BrightnessPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindDialogView(View view) {
|
||||
super.onBindDialogView(view);
|
||||
|
||||
mSeekBar = getSeekBar(view);
|
||||
mSeekBar.setOnSeekBarChangeListener(this);
|
||||
mSeekBar.setMax(MAXIMUM_BACKLIGHT - MINIMUM_BACKLIGHT);
|
||||
try {
|
||||
mOldBrightness = Settings.System.getInt(getContext().getContentResolver(),
|
||||
Settings.System.SCREEN_BRIGHTNESS);
|
||||
} catch (SettingNotFoundException snfe) {
|
||||
mOldBrightness = MAXIMUM_BACKLIGHT;
|
||||
}
|
||||
mSeekBar.setProgress(mOldBrightness - MINIMUM_BACKLIGHT);
|
||||
}
|
||||
|
||||
public void onProgressChanged(SeekBar seekBar, int progress,
|
||||
boolean fromTouch) {
|
||||
setBrightness(progress + MINIMUM_BACKLIGHT);
|
||||
}
|
||||
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
// NA
|
||||
}
|
||||
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
// NA
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDialogClosed(boolean positiveResult) {
|
||||
super.onDialogClosed(positiveResult);
|
||||
|
||||
if (positiveResult) {
|
||||
Settings.System.putInt(getContext().getContentResolver(),
|
||||
Settings.System.SCREEN_BRIGHTNESS,
|
||||
mSeekBar.getProgress() + MINIMUM_BACKLIGHT);
|
||||
} else {
|
||||
setBrightness(mOldBrightness);
|
||||
}
|
||||
}
|
||||
|
||||
private void setBrightness(int brightness) {
|
||||
try {
|
||||
IHardwareService hardware = IHardwareService.Stub.asInterface(
|
||||
ServiceManager.getService("hardware"));
|
||||
if (hardware != null) {
|
||||
hardware.setScreenBacklight(brightness);
|
||||
}
|
||||
} catch (RemoteException doe) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
480
src/com/android/settings/ChooseLockPattern.java
Normal file
480
src/com/android/settings/ChooseLockPattern.java
Normal file
@@ -0,0 +1,480 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import com.google.android.collect.Lists;
|
||||
|
||||
import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.LockPatternView;
|
||||
import static com.android.internal.widget.LockPatternView.DisplayMode;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* If the user has a lock pattern set already, makes them confirm the existing one.
|
||||
*
|
||||
* Then, prompts the user to choose a lock pattern:
|
||||
* - prompts for initial pattern
|
||||
* - asks for confirmation / restart
|
||||
* - saves chosen password when confirmed
|
||||
*/
|
||||
public class ChooseLockPattern extends Activity implements View.OnClickListener{
|
||||
|
||||
// how long after a confirmation message is shown before moving on
|
||||
static final int INFORMATION_MSG_TIMEOUT_MS = 3000;
|
||||
|
||||
// how long we wait to clear a wrong pattern
|
||||
private static final int WRONG_PATTERN_CLEAR_TIMEOUT_MS = 2000;
|
||||
|
||||
private static final int ID_EMPTY_MESSAGE = -1;
|
||||
|
||||
|
||||
protected TextView mHeaderText;
|
||||
protected LockPatternView mLockPatternView;
|
||||
protected TextView mFooterText;
|
||||
private TextView mFooterLeftButton;
|
||||
private TextView mFooterRightButton;
|
||||
|
||||
protected List<LockPatternView.Cell> mChosenPattern = null;
|
||||
|
||||
protected LockPatternUtils mLockPatternUtils;
|
||||
|
||||
/**
|
||||
* The patten used during the help screen to show how to draw a pattern.
|
||||
*/
|
||||
private final List<LockPatternView.Cell> mAnimatePattern =
|
||||
Collections.unmodifiableList(
|
||||
Lists.newArrayList(
|
||||
LockPatternView.Cell.of(0, 0),
|
||||
LockPatternView.Cell.of(0, 1),
|
||||
LockPatternView.Cell.of(1, 1),
|
||||
LockPatternView.Cell.of(2, 1)
|
||||
));
|
||||
|
||||
|
||||
/**
|
||||
* The pattern listener that responds according to a user choosing a new
|
||||
* lock pattern.
|
||||
*/
|
||||
protected LockPatternView.OnPatternListener mChooseNewLockPatternListener = new LockPatternView.OnPatternListener() {
|
||||
|
||||
public void onPatternStart() {
|
||||
mLockPatternView.removeCallbacks(mClearPatternRunnable);
|
||||
patternInProgress();
|
||||
}
|
||||
|
||||
public void onPatternCleared() {
|
||||
mLockPatternView.removeCallbacks(mClearPatternRunnable);
|
||||
}
|
||||
|
||||
public void onPatternDetected(List<LockPatternView.Cell> pattern) {
|
||||
if (mUiStage == Stage.NeedToConfirm || mUiStage == Stage.ConfirmWrong) {
|
||||
if (mChosenPattern == null) throw new IllegalStateException("null chosen pattern in stage 'need to confirm");
|
||||
if (mChosenPattern.equals(pattern)) {
|
||||
updateStage(Stage.ChoiceConfirmed);
|
||||
} else {
|
||||
updateStage(Stage.ConfirmWrong);
|
||||
}
|
||||
} else if (mUiStage == Stage.Introduction || mUiStage == Stage.ChoiceTooShort){
|
||||
if (pattern.size() < LockPatternUtils.MIN_LOCK_PATTERN_SIZE) {
|
||||
updateStage(Stage.ChoiceTooShort);
|
||||
} else {
|
||||
mChosenPattern = new ArrayList<LockPatternView.Cell>(pattern);
|
||||
updateStage(Stage.FirstChoiceValid);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("Unexpected stage " + mUiStage + " when "
|
||||
+ "entering the pattern.");
|
||||
}
|
||||
}
|
||||
|
||||
private void patternInProgress() {
|
||||
mHeaderText.setText(R.string.lockpattern_recording_inprogress);
|
||||
mFooterText.setText("");
|
||||
mFooterLeftButton.setEnabled(false);
|
||||
mFooterRightButton.setEnabled(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The states of the left footer button.
|
||||
*/
|
||||
enum LeftButtonMode {
|
||||
Cancel(R.string.cancel, true),
|
||||
CancelDisabled(R.string.cancel, false),
|
||||
Retry(R.string.lockpattern_retry_button_text, true),
|
||||
RetryDisabled(R.string.lockpattern_retry_button_text, false),
|
||||
Gone(ID_EMPTY_MESSAGE, false);
|
||||
|
||||
|
||||
/**
|
||||
* @param text The displayed text for this mode.
|
||||
* @param enabled Whether the button should be enabled.
|
||||
*/
|
||||
LeftButtonMode(int text, boolean enabled) {
|
||||
this.text = text;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
final int text;
|
||||
final boolean enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* The states of the right button.
|
||||
*/
|
||||
enum RightButtonMode {
|
||||
Continue(R.string.lockpattern_continue_button_text, true),
|
||||
ContinueDisabled(R.string.lockpattern_continue_button_text, false),
|
||||
Confirm(R.string.lockpattern_confirm_button_text, true),
|
||||
ConfirmDisabled(R.string.lockpattern_confirm_button_text, false),
|
||||
Ok(android.R.string.ok, true);
|
||||
|
||||
/**
|
||||
* @param text The displayed text for this mode.
|
||||
* @param enabled Whether the button should be enabled.
|
||||
*/
|
||||
RightButtonMode(int text, boolean enabled) {
|
||||
this.text = text;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
final int text;
|
||||
final boolean enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep track internally of where the user is in choosing a pattern.
|
||||
*/
|
||||
protected enum Stage {
|
||||
|
||||
Introduction(
|
||||
R.string.lockpattern_recording_intro_header,
|
||||
LeftButtonMode.Cancel, RightButtonMode.ContinueDisabled,
|
||||
R.string.lockpattern_recording_intro_footer, true),
|
||||
HelpScreen(
|
||||
R.string.lockpattern_settings_help_how_to_record,
|
||||
LeftButtonMode.Gone, RightButtonMode.Ok, ID_EMPTY_MESSAGE, false),
|
||||
ChoiceTooShort(
|
||||
R.string.lockpattern_recording_incorrect_too_short,
|
||||
LeftButtonMode.Retry, RightButtonMode.ContinueDisabled,
|
||||
ID_EMPTY_MESSAGE, true),
|
||||
FirstChoiceValid(
|
||||
R.string.lockpattern_pattern_entered_header,
|
||||
LeftButtonMode.Retry, RightButtonMode.Continue, ID_EMPTY_MESSAGE, false),
|
||||
NeedToConfirm(
|
||||
R.string.lockpattern_need_to_confirm,
|
||||
LeftButtonMode.CancelDisabled, RightButtonMode.ConfirmDisabled,
|
||||
ID_EMPTY_MESSAGE, true),
|
||||
ConfirmWrong(
|
||||
R.string.lockpattern_need_to_unlock_wrong,
|
||||
LeftButtonMode.Cancel, RightButtonMode.ConfirmDisabled,
|
||||
ID_EMPTY_MESSAGE, true),
|
||||
ChoiceConfirmed(
|
||||
R.string.lockpattern_pattern_confirmed_header,
|
||||
LeftButtonMode.Cancel, RightButtonMode.Confirm, ID_EMPTY_MESSAGE, false);
|
||||
|
||||
|
||||
/**
|
||||
* @param headerMessage The message displayed at the top.
|
||||
* @param leftMode The mode of the left button.
|
||||
* @param rightMode The mode of the right button.
|
||||
* @param footerMessage The footer message.
|
||||
* @param patternEnabled Whether the pattern widget is enabled.
|
||||
*/
|
||||
Stage(int headerMessage,
|
||||
LeftButtonMode leftMode,
|
||||
RightButtonMode rightMode,
|
||||
int footerMessage, boolean patternEnabled) {
|
||||
this.headerMessage = headerMessage;
|
||||
this.leftMode = leftMode;
|
||||
this.rightMode = rightMode;
|
||||
this.footerMessage = footerMessage;
|
||||
this.patternEnabled = patternEnabled;
|
||||
}
|
||||
|
||||
final int headerMessage;
|
||||
final LeftButtonMode leftMode;
|
||||
final RightButtonMode rightMode;
|
||||
final int footerMessage;
|
||||
final boolean patternEnabled;
|
||||
}
|
||||
|
||||
private Stage mUiStage = Stage.Introduction;
|
||||
|
||||
private Runnable mClearPatternRunnable = new Runnable() {
|
||||
public void run() {
|
||||
mLockPatternView.clearPattern();
|
||||
}
|
||||
};
|
||||
|
||||
private static final String KEY_UI_STAGE = "uiStage";
|
||||
private static final String KEY_PATTERN_CHOICE = "chosenPattern";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mLockPatternUtils = new LockPatternUtils(getContentResolver());
|
||||
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
|
||||
setupViews();
|
||||
|
||||
// make it so unhandled touch events within the unlock screen go to the
|
||||
// lock pattern view.
|
||||
final LinearLayoutWithDefaultTouchRecepient topLayout
|
||||
= (LinearLayoutWithDefaultTouchRecepient) findViewById(
|
||||
R.id.topLayout);
|
||||
topLayout.setDefaultTouchRecepient(mLockPatternView);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
// first launch
|
||||
updateStage(Stage.Introduction);
|
||||
if (mLockPatternUtils.savedPatternExists()) {
|
||||
confirmPattern();
|
||||
}
|
||||
} else {
|
||||
// restore from previous state
|
||||
final String patternString = savedInstanceState.getString(KEY_PATTERN_CHOICE);
|
||||
if (patternString != null) {
|
||||
mChosenPattern = LockPatternUtils.stringToPattern(patternString);
|
||||
}
|
||||
updateStage(Stage.values()[savedInstanceState.getInt(KEY_UI_STAGE)]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep all "find view" related stuff confined to this function since in
|
||||
* case someone needs to subclass and customize.
|
||||
*/
|
||||
protected void setupViews() {
|
||||
setContentView(R.layout.choose_lock_pattern);
|
||||
|
||||
mHeaderText = (TextView) findViewById(R.id.headerText);
|
||||
|
||||
mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
|
||||
mLockPatternView.setOnPatternListener(mChooseNewLockPatternListener);
|
||||
|
||||
mFooterText = (TextView) findViewById(R.id.footerText);
|
||||
|
||||
mFooterLeftButton = (TextView) findViewById(R.id.footerLeftButton);
|
||||
mFooterRightButton = (TextView) findViewById(R.id.footerRightButton);
|
||||
|
||||
mFooterLeftButton.setOnClickListener(this);
|
||||
mFooterRightButton.setOnClickListener(this);
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
if (v == mFooterLeftButton) {
|
||||
if (mUiStage.leftMode == LeftButtonMode.Retry) {
|
||||
mChosenPattern = null;
|
||||
mLockPatternView.clearPattern();
|
||||
updateStage(Stage.Introduction);
|
||||
} else if (mUiStage.leftMode == LeftButtonMode.Cancel) {
|
||||
finish();
|
||||
} else {
|
||||
throw new IllegalStateException("left footer button pressed, but stage of " +
|
||||
mUiStage + " doesn't make sense");
|
||||
}
|
||||
} else if (v == mFooterRightButton) {
|
||||
|
||||
if (mUiStage.rightMode == RightButtonMode.Continue) {
|
||||
if (mUiStage != Stage.FirstChoiceValid) {
|
||||
throw new IllegalStateException("expected ui stage " + Stage.FirstChoiceValid
|
||||
+ " when button is " + RightButtonMode.Continue);
|
||||
}
|
||||
updateStage(Stage.NeedToConfirm);
|
||||
} else if (mUiStage.rightMode == RightButtonMode.Confirm) {
|
||||
if (mUiStage != Stage.ChoiceConfirmed) {
|
||||
throw new IllegalStateException("expected ui stage " + Stage.ChoiceConfirmed
|
||||
+ " when button is " + RightButtonMode.Confirm);
|
||||
}
|
||||
saveChosenPatternAndFinish();
|
||||
} else if (mUiStage.rightMode == RightButtonMode.Ok) {
|
||||
if (mUiStage != Stage.HelpScreen) {
|
||||
throw new IllegalStateException("Help screen is only mode with ok button, but " +
|
||||
"stage is " + mUiStage);
|
||||
}
|
||||
mLockPatternView.clearPattern();
|
||||
mLockPatternView.setDisplayMode(DisplayMode.Correct);
|
||||
updateStage(Stage.Introduction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
|
||||
if (mUiStage == Stage.HelpScreen) {
|
||||
updateStage(Stage.Introduction);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU && mUiStage == Stage.Introduction) {
|
||||
updateStage(Stage.HelpScreen);
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch screen to confirm the existing lock pattern.
|
||||
* @see #onActivityResult(int, int, android.content.Intent)
|
||||
*/
|
||||
protected void confirmPattern() {
|
||||
final Intent intent = new Intent();
|
||||
intent.setClassName("com.android.settings", "com.android.settings.ConfirmLockPattern");
|
||||
startActivityForResult(intent, 55);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #confirmPattern
|
||||
*/
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode,
|
||||
Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (requestCode != 55) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (resultCode != Activity.RESULT_OK) {
|
||||
finish();
|
||||
}
|
||||
updateStage(Stage.Introduction);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putInt(KEY_UI_STAGE, mUiStage.ordinal());
|
||||
if (mChosenPattern != null) {
|
||||
outState.putString(KEY_PATTERN_CHOICE, LockPatternUtils.patternToString(mChosenPattern));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the messages and buttons appropriate to what stage the user
|
||||
* is at in choosing a view. This doesn't handle clearing out the pattern;
|
||||
* the pattern is expected to be in the right state.
|
||||
* @param stage
|
||||
*/
|
||||
protected void updateStage(Stage stage) {
|
||||
|
||||
mUiStage = stage;
|
||||
|
||||
// header text, footer text, visibility and
|
||||
// enabled state all known from the stage
|
||||
if (stage == Stage.ChoiceTooShort) {
|
||||
mHeaderText.setText(
|
||||
getResources().getString(
|
||||
stage.headerMessage,
|
||||
LockPatternUtils.MIN_LOCK_PATTERN_SIZE));
|
||||
} else {
|
||||
mHeaderText.setText(stage.headerMessage);
|
||||
}
|
||||
if (stage.footerMessage == ID_EMPTY_MESSAGE) {
|
||||
mFooterText.setText("");
|
||||
} else {
|
||||
mFooterText.setText(stage.footerMessage);
|
||||
}
|
||||
|
||||
if (stage.leftMode == LeftButtonMode.Gone) {
|
||||
mFooterLeftButton.setVisibility(View.GONE);
|
||||
} else {
|
||||
mFooterLeftButton.setVisibility(View.VISIBLE);
|
||||
mFooterLeftButton.setText(stage.leftMode.text);
|
||||
mFooterLeftButton.setEnabled(stage.leftMode.enabled);
|
||||
}
|
||||
|
||||
mFooterRightButton.setText(stage.rightMode.text);
|
||||
mFooterRightButton.setEnabled(stage.rightMode.enabled);
|
||||
|
||||
// same for whether the patten is enabled
|
||||
if (stage.patternEnabled) {
|
||||
mLockPatternView.enableInput();
|
||||
} else {
|
||||
mLockPatternView.disableInput();
|
||||
}
|
||||
|
||||
// the rest of the stuff varies enough that it is easier just to handle
|
||||
// on a case by case basis.
|
||||
mLockPatternView.setDisplayMode(DisplayMode.Correct);
|
||||
|
||||
switch (mUiStage) {
|
||||
case Introduction:
|
||||
mLockPatternView.clearPattern();
|
||||
break;
|
||||
case HelpScreen:
|
||||
mLockPatternView.setPattern(DisplayMode.Animate, mAnimatePattern);
|
||||
break;
|
||||
case ChoiceTooShort:
|
||||
mLockPatternView.setDisplayMode(DisplayMode.Wrong);
|
||||
postClearPatternRunnable();
|
||||
break;
|
||||
case FirstChoiceValid:
|
||||
break;
|
||||
case NeedToConfirm:
|
||||
mLockPatternView.clearPattern();
|
||||
break;
|
||||
case ConfirmWrong:
|
||||
mLockPatternView.setDisplayMode(DisplayMode.Wrong);
|
||||
postClearPatternRunnable();
|
||||
break;
|
||||
case ChoiceConfirmed:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// clear the wrong pattern unless they have started a new one
|
||||
// already
|
||||
private void postClearPatternRunnable() {
|
||||
mLockPatternView.removeCallbacks(mClearPatternRunnable);
|
||||
mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
private void saveChosenPatternAndFinish() {
|
||||
boolean patternExistedBefore = mLockPatternUtils.savedPatternExists();
|
||||
mLockPatternUtils.saveLockPattern(mChosenPattern);
|
||||
|
||||
// if setting pattern for first time, enable the lock gesture. otherwise,
|
||||
// keep the user's setting.
|
||||
if (!patternExistedBefore) {
|
||||
mLockPatternUtils.setLockPatternEnabled(true);
|
||||
mLockPatternUtils.setVisiblePatternEnabled(true);
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
94
src/com/android/settings/ChooseLockPatternExample.java
Normal file
94
src/com/android/settings/ChooseLockPatternExample.java
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.AnimationDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
public class ChooseLockPatternExample extends Activity implements View.OnClickListener {
|
||||
private static final long START_DELAY = 1000;
|
||||
protected static final String TAG = "Settings";
|
||||
private View mNextButton;
|
||||
private View mSkipButton;
|
||||
private View mImageView;
|
||||
private AnimationDrawable mAnimation;
|
||||
private Handler mHandler = new Handler();
|
||||
private Runnable mRunnable = new Runnable() {
|
||||
public void run() {
|
||||
startAnimation(mAnimation);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.choose_lock_pattern_example);
|
||||
initViews();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mHandler.postDelayed(mRunnable, START_DELAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
stopAnimation(mAnimation);
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
if (v == mSkipButton) {
|
||||
finish();
|
||||
} else if (v == mNextButton) {
|
||||
stopAnimation(mAnimation);
|
||||
Intent intent = new Intent(this, ChooseLockPattern.class);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
mNextButton = findViewById(R.id.next_button);
|
||||
mNextButton.setOnClickListener(this);
|
||||
|
||||
mSkipButton = findViewById(R.id.skip_button);
|
||||
mSkipButton.setOnClickListener(this);
|
||||
|
||||
mImageView = (ImageView) findViewById(R.id.lock_anim);
|
||||
mImageView.setBackgroundResource(R.drawable.lock_anim);
|
||||
mImageView.setOnClickListener(this);
|
||||
mAnimation = (AnimationDrawable) mImageView.getBackground();
|
||||
}
|
||||
|
||||
protected void startAnimation(final AnimationDrawable animation) {
|
||||
if (animation != null && !animation.isRunning()) {
|
||||
animation.run();
|
||||
}
|
||||
}
|
||||
|
||||
protected void stopAnimation(final AnimationDrawable animation) {
|
||||
if (animation != null && animation.isRunning()) animation.stop();
|
||||
}
|
||||
}
|
||||
|
||||
62
src/com/android/settings/ChooseLockPatternTutorial.java
Normal file
62
src/com/android/settings/ChooseLockPatternTutorial.java
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
public class ChooseLockPatternTutorial extends Activity implements View.OnClickListener {
|
||||
protected View mNextButton;
|
||||
protected View mSkipButton;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
// Don't show the tutorial if the user has seen it before.
|
||||
LockPatternUtils lockPatternUtils = new LockPatternUtils(getContentResolver());
|
||||
if (savedInstanceState == null && lockPatternUtils.savedPatternExists()) {
|
||||
Intent intent = new Intent();
|
||||
intent.setClassName("com.android.settings", "com.android.settings.ChooseLockPattern");
|
||||
startActivity(intent);
|
||||
finish();
|
||||
} else {
|
||||
initViews();
|
||||
}
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
setContentView(R.layout.choose_lock_pattern_tutorial);
|
||||
mNextButton = findViewById(R.id.next_button);
|
||||
mNextButton.setOnClickListener(this);
|
||||
mSkipButton = findViewById(R.id.skip_button);
|
||||
mSkipButton.setOnClickListener(this);
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
if (v == mSkipButton) {
|
||||
finish();
|
||||
} else if (v == mNextButton) {
|
||||
startActivity(new Intent(this, ChooseLockPatternExample.class));
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
260
src/com/android/settings/ConfirmLockPattern.java
Normal file
260
src/com/android/settings/ConfirmLockPattern.java
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.LockPatternView;
|
||||
import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.SystemClock;
|
||||
import android.os.Bundle;
|
||||
import android.widget.TextView;
|
||||
import android.view.Window;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Launch this when you want the user to confirm their lock pattern.
|
||||
*
|
||||
* Sets an activity result of {@link Activity#RESULT_OK} when the user
|
||||
* successfully confirmed their pattern.
|
||||
*/
|
||||
public class ConfirmLockPattern extends Activity {
|
||||
|
||||
/**
|
||||
* Names of {@link CharSequence} fields within the originating {@link Intent}
|
||||
* that are used to configure the keyguard confirmation view's labeling.
|
||||
* The view will use the system-defined resource strings for any labels that
|
||||
* the caller does not supply.
|
||||
*/
|
||||
public static final String HEADER_TEXT = "com.android.settings.ConfirmLockPattern.header";
|
||||
public static final String FOOTER_TEXT = "com.android.settings.ConfirmLockPattern.footer";
|
||||
public static final String HEADER_WRONG_TEXT = "com.android.settings.ConfirmLockPattern.header_wrong";
|
||||
public static final String FOOTER_WRONG_TEXT = "com.android.settings.ConfirmLockPattern.footer_wrong";
|
||||
|
||||
// how long we wait to clear a wrong pattern
|
||||
private static final int WRONG_PATTERN_CLEAR_TIMEOUT_MS = 2000;
|
||||
|
||||
private static final String KEY_NUM_WRONG_ATTEMPTS = "num_wrong_attempts";
|
||||
|
||||
private LockPatternView mLockPatternView;
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
private int mNumWrongConfirmAttempts;
|
||||
private CountDownTimer mCountdownTimer;
|
||||
|
||||
private TextView mHeaderTextView;
|
||||
private TextView mFooterTextView;
|
||||
|
||||
// caller-supplied text for various prompts
|
||||
private CharSequence mHeaderText;
|
||||
private CharSequence mFooterText;
|
||||
private CharSequence mHeaderWrongText;
|
||||
private CharSequence mFooterWrongText;
|
||||
|
||||
|
||||
private enum Stage {
|
||||
NeedToUnlock,
|
||||
NeedToUnlockWrong,
|
||||
LockedOut
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mLockPatternUtils = new LockPatternUtils(getContentResolver());
|
||||
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
setContentView(R.layout.confirm_lock_pattern);
|
||||
|
||||
mHeaderTextView = (TextView) findViewById(R.id.headerText);
|
||||
mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
|
||||
mFooterTextView = (TextView) findViewById(R.id.footerText);
|
||||
|
||||
// make it so unhandled touch events within the unlock screen go to the
|
||||
// lock pattern view.
|
||||
final LinearLayoutWithDefaultTouchRecepient topLayout
|
||||
= (LinearLayoutWithDefaultTouchRecepient) findViewById(
|
||||
R.id.topLayout);
|
||||
topLayout.setDefaultTouchRecepient(mLockPatternView);
|
||||
|
||||
Intent intent = getIntent();
|
||||
if (intent != null) {
|
||||
mHeaderText = intent.getCharSequenceExtra(HEADER_TEXT);
|
||||
mFooterText = intent.getCharSequenceExtra(FOOTER_TEXT);
|
||||
mHeaderWrongText = intent.getCharSequenceExtra(HEADER_WRONG_TEXT);
|
||||
mFooterWrongText = intent.getCharSequenceExtra(FOOTER_WRONG_TEXT);
|
||||
}
|
||||
|
||||
mLockPatternView.setOnPatternListener(mConfirmExistingLockPatternListener);
|
||||
updateStage(Stage.NeedToUnlock);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
mNumWrongConfirmAttempts = savedInstanceState.getInt(KEY_NUM_WRONG_ATTEMPTS);
|
||||
} else {
|
||||
// on first launch, if no lock pattern is set, then finish with
|
||||
// success (don't want user to get stuck confirming something that
|
||||
// doesn't exist).
|
||||
if (!mLockPatternUtils.savedPatternExists()) {
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
// deliberately not calling super since we are managing this in full
|
||||
outState.putInt(KEY_NUM_WRONG_ATTEMPTS, mNumWrongConfirmAttempts);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (mCountdownTimer != null) {
|
||||
mCountdownTimer.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
// if the user is currently locked out, enforce it.
|
||||
long deadline = mLockPatternUtils.getLockoutAttemptDeadline();
|
||||
if (deadline != 0) {
|
||||
handleAttemptLockout(deadline);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStage(Stage stage) {
|
||||
|
||||
switch (stage) {
|
||||
case NeedToUnlock:
|
||||
if (mHeaderText != null) {
|
||||
mHeaderTextView.setText(mHeaderText);
|
||||
} else {
|
||||
mHeaderTextView.setText(R.string.lockpattern_need_to_unlock);
|
||||
}
|
||||
if (mFooterText != null) {
|
||||
mFooterTextView.setText(mFooterText);
|
||||
} else {
|
||||
mFooterTextView.setText(R.string.lockpattern_need_to_unlock_footer);
|
||||
}
|
||||
|
||||
mLockPatternView.setEnabled(true);
|
||||
mLockPatternView.enableInput();
|
||||
break;
|
||||
case NeedToUnlockWrong:
|
||||
if (mHeaderWrongText != null) {
|
||||
mHeaderTextView.setText(mHeaderWrongText);
|
||||
} else {
|
||||
mHeaderTextView.setText(R.string.lockpattern_need_to_unlock_wrong);
|
||||
}
|
||||
if (mFooterWrongText != null) {
|
||||
mFooterTextView.setText(mFooterWrongText);
|
||||
} else {
|
||||
mFooterTextView.setText(R.string.lockpattern_need_to_unlock_wrong_footer);
|
||||
}
|
||||
|
||||
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
|
||||
mLockPatternView.setEnabled(true);
|
||||
mLockPatternView.enableInput();
|
||||
break;
|
||||
case LockedOut:
|
||||
mLockPatternView.clearPattern();
|
||||
// enabled = false means: disable input, and have the
|
||||
// appearance of being disabled.
|
||||
mLockPatternView.setEnabled(false); // appearance of being disabled
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private Runnable mClearPatternRunnable = new Runnable() {
|
||||
public void run() {
|
||||
mLockPatternView.clearPattern();
|
||||
}
|
||||
};
|
||||
|
||||
// clear the wrong pattern unless they have started a new one
|
||||
// already
|
||||
private void postClearPatternRunnable() {
|
||||
mLockPatternView.removeCallbacks(mClearPatternRunnable);
|
||||
mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
* The pattern listener that responds according to a user confirming
|
||||
* an existing lock pattern.
|
||||
*/
|
||||
private LockPatternView.OnPatternListener mConfirmExistingLockPatternListener = new LockPatternView.OnPatternListener() {
|
||||
|
||||
public void onPatternStart() {
|
||||
mLockPatternView.removeCallbacks(mClearPatternRunnable);
|
||||
}
|
||||
|
||||
public void onPatternCleared() {
|
||||
mLockPatternView.removeCallbacks(mClearPatternRunnable);
|
||||
}
|
||||
|
||||
public void onPatternDetected(List<LockPatternView.Cell> pattern) {
|
||||
if (mLockPatternUtils.checkPattern(pattern)) {
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
} else {
|
||||
if (pattern.size() >= LockPatternUtils.MIN_LOCK_PATTERN_SIZE &&
|
||||
++mNumWrongConfirmAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
|
||||
long deadline = SystemClock.elapsedRealtime() + LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS;
|
||||
mLockPatternUtils.setLockoutAttemptDeadline(deadline);
|
||||
handleAttemptLockout(deadline);
|
||||
} else {
|
||||
updateStage(Stage.NeedToUnlockWrong);
|
||||
postClearPatternRunnable();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private void handleAttemptLockout(long elapsedRealtimeDeadline) {
|
||||
updateStage(Stage.LockedOut);
|
||||
long elapsedRealtime = SystemClock.elapsedRealtime();
|
||||
mCountdownTimer = new CountDownTimer(
|
||||
elapsedRealtimeDeadline - elapsedRealtime,
|
||||
LockPatternUtils.FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS) {
|
||||
|
||||
@Override
|
||||
public void onTick(long millisUntilFinished) {
|
||||
mHeaderTextView.setText(R.string.lockpattern_too_many_failed_confirmation_attempts_header);
|
||||
final int secondsCountdown = (int) (millisUntilFinished / 1000);
|
||||
mFooterTextView.setText(getString(
|
||||
R.string.lockpattern_too_many_failed_confirmation_attempts_footer,
|
||||
secondsCountdown));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
mNumWrongConfirmAttempts = 0;
|
||||
updateStage(Stage.NeedToUnlock);
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
363
src/com/android/settings/DateTimeSettings.java
Normal file
363
src/com/android/settings/DateTimeSettings.java
Normal file
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.app.DatePickerDialog;
|
||||
import android.app.TimePickerDialog;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.pim.DateFormat;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.SettingNotFoundException;
|
||||
import android.widget.DatePicker;
|
||||
import android.widget.TimePicker;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class DateTimeSettings
|
||||
extends PreferenceActivity
|
||||
implements OnSharedPreferenceChangeListener,
|
||||
TimePickerDialog.OnTimeSetListener , DatePickerDialog.OnDateSetListener {
|
||||
|
||||
private static final String HOURS_12 = "12";
|
||||
private static final String HOURS_24 = "24";
|
||||
|
||||
private Calendar mDummyDate;
|
||||
private static final String KEY_DATE_FORMAT = "date_format";
|
||||
private static final String KEY_AUTO_TIME = "auto_time";
|
||||
|
||||
private static final int DIALOG_DATEPICKER = 0;
|
||||
private static final int DIALOG_TIMEPICKER = 1;
|
||||
|
||||
private CheckBoxPreference mAutoPref;
|
||||
private Preference mTimePref;
|
||||
private Preference mTime24Pref;
|
||||
private Preference mTimeZone;
|
||||
private Preference mDatePref;
|
||||
private ListPreference mDateFormat;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
addPreferencesFromResource(R.xml.date_time_prefs);
|
||||
|
||||
initUI();
|
||||
}
|
||||
|
||||
private void initUI() {
|
||||
boolean autoEnabled = getAutoState();
|
||||
|
||||
mDummyDate = Calendar.getInstance();
|
||||
mDummyDate.set(mDummyDate.get(Calendar.YEAR), 11, 31, 13, 0, 0);
|
||||
|
||||
mAutoPref = (CheckBoxPreference) findPreference(KEY_AUTO_TIME);
|
||||
mAutoPref.setChecked(autoEnabled);
|
||||
mTimePref = findPreference("time");
|
||||
mTime24Pref = findPreference("24 hour");
|
||||
mTimeZone = findPreference("timezone");
|
||||
mDatePref = findPreference("date");
|
||||
mDateFormat = (ListPreference) findPreference(KEY_DATE_FORMAT);
|
||||
|
||||
int currentFormatIndex = -1;
|
||||
String [] dateFormats = getResources().getStringArray(R.array.date_format_values);
|
||||
String [] formattedDates = new String[dateFormats.length];
|
||||
String currentFormat = getDateFormat();
|
||||
// Initialize if DATE_FORMAT is not set in the system settings
|
||||
// This can happen after a factory reset (or data wipe)
|
||||
if (currentFormat == null) {
|
||||
currentFormat = getResources().getString(R.string.default_date_format);
|
||||
setDateFormat(currentFormat);
|
||||
}
|
||||
for (int i = 0; i < formattedDates.length; i++) {
|
||||
formattedDates[i] = DateFormat.format(dateFormats[i], mDummyDate).toString();
|
||||
if (currentFormat.equals(dateFormats[i])) currentFormatIndex = i;
|
||||
}
|
||||
|
||||
mDateFormat.setEntries(formattedDates);
|
||||
mDateFormat.setEntryValues(R.array.date_format_values);
|
||||
mDateFormat.setValue(currentFormat);
|
||||
|
||||
mTimePref.setEnabled(!autoEnabled);
|
||||
mDatePref.setEnabled(!autoEnabled);
|
||||
mTimeZone.setEnabled(!autoEnabled);
|
||||
|
||||
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
((CheckBoxPreference)mTime24Pref).setChecked(is24Hour());
|
||||
|
||||
// Register for time ticks and other reasons for time change
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_TIME_TICK);
|
||||
filter.addAction(Intent.ACTION_TIME_CHANGED);
|
||||
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
|
||||
registerReceiver(mIntentReceiver, filter, null, null);
|
||||
|
||||
updateTimeAndDateDisplay();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
unregisterReceiver(mIntentReceiver);
|
||||
}
|
||||
|
||||
private void updateTimeAndDateDisplay() {
|
||||
java.text.DateFormat shortDateFormat = DateFormat.getDateFormat(this);
|
||||
Date now = Calendar.getInstance().getTime();
|
||||
Date dummyDate = mDummyDate.getTime();
|
||||
mTimePref.setSummary(DateFormat.getTimeFormat(this).format(now));
|
||||
mTimeZone.setSummary(getTimeZoneText());
|
||||
mDatePref.setSummary(shortDateFormat.format(now));
|
||||
mDateFormat.setSummary(shortDateFormat.format(dummyDate));
|
||||
}
|
||||
|
||||
public void onDateSet(DatePicker view, int year, int month, int day) {
|
||||
Calendar c = Calendar.getInstance();
|
||||
|
||||
c.set(Calendar.YEAR, year);
|
||||
c.set(Calendar.MONTH, month);
|
||||
c.set(Calendar.DAY_OF_MONTH, day);
|
||||
long when = c.getTimeInMillis();
|
||||
|
||||
if (when / 1000 < Integer.MAX_VALUE) {
|
||||
SystemClock.setCurrentTimeMillis(when);
|
||||
}
|
||||
updateTimeAndDateDisplay();
|
||||
}
|
||||
|
||||
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
|
||||
Calendar c = Calendar.getInstance();
|
||||
|
||||
c.set(Calendar.HOUR_OF_DAY, hourOfDay);
|
||||
c.set(Calendar.MINUTE, minute);
|
||||
long when = c.getTimeInMillis();
|
||||
|
||||
if (when / 1000 < Integer.MAX_VALUE) {
|
||||
SystemClock.setCurrentTimeMillis(when);
|
||||
}
|
||||
updateTimeAndDateDisplay();
|
||||
timeUpdated();
|
||||
}
|
||||
|
||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||
if (key.equals(KEY_DATE_FORMAT)) {
|
||||
String format = preferences.getString(key,
|
||||
getResources().getString(R.string.default_date_format));
|
||||
Settings.System.putString(getContentResolver(),
|
||||
Settings.System.DATE_FORMAT, format);
|
||||
updateTimeAndDateDisplay();
|
||||
} else if (key.equals(KEY_AUTO_TIME)) {
|
||||
boolean autoEnabled = preferences.getBoolean(key, true);
|
||||
Settings.System.putInt(getContentResolver(),
|
||||
Settings.System.AUTO_TIME,
|
||||
autoEnabled ? 1 : 0);
|
||||
mTimePref.setEnabled(!autoEnabled);
|
||||
mDatePref.setEnabled(!autoEnabled);
|
||||
mTimeZone.setEnabled(!autoEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
public Dialog onCreateDialog(int id) {
|
||||
Dialog d;
|
||||
|
||||
switch (id) {
|
||||
case DIALOG_DATEPICKER: {
|
||||
final Calendar calendar = Calendar.getInstance();
|
||||
d = new DatePickerDialog(
|
||||
this,
|
||||
this,
|
||||
calendar.get(Calendar.YEAR),
|
||||
calendar.get(Calendar.MONTH),
|
||||
calendar.get(Calendar.DAY_OF_MONTH));
|
||||
d.setTitle(getResources().getString(R.string.date_time_changeDate_text));
|
||||
break;
|
||||
}
|
||||
case DIALOG_TIMEPICKER: {
|
||||
final Calendar calendar = Calendar.getInstance();
|
||||
d = new TimePickerDialog(
|
||||
this,
|
||||
this,
|
||||
calendar.get(Calendar.HOUR_OF_DAY),
|
||||
calendar.get(Calendar.MINUTE),
|
||||
DateFormat.is24HourFormat(this));
|
||||
d.setTitle(getResources().getString(R.string.date_time_changeTime_text));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
d = null;
|
||||
break;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
public void onPrepareDialog(int id, Dialog d) {
|
||||
switch (id) {
|
||||
case DIALOG_DATEPICKER: {
|
||||
DatePickerDialog datePicker = (DatePickerDialog)d;
|
||||
final Calendar calendar = Calendar.getInstance();
|
||||
datePicker.updateDate(
|
||||
calendar.get(Calendar.YEAR),
|
||||
calendar.get(Calendar.MONTH),
|
||||
calendar.get(Calendar.DAY_OF_MONTH));
|
||||
break;
|
||||
}
|
||||
case DIALOG_TIMEPICKER: {
|
||||
TimePickerDialog timePicker = (TimePickerDialog)d;
|
||||
final Calendar calendar = Calendar.getInstance();
|
||||
timePicker.updateTime(
|
||||
calendar.get(Calendar.HOUR_OF_DAY),
|
||||
calendar.get(Calendar.MINUTE));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
|
||||
if (preference == mDatePref) {
|
||||
showDialog(DIALOG_DATEPICKER);
|
||||
} else if (preference == mTimePref) {
|
||||
showDialog(DIALOG_TIMEPICKER);
|
||||
} else if (preference == mTime24Pref) {
|
||||
set24Hour(((CheckBoxPreference)mTime24Pref).isChecked());
|
||||
updateTimeAndDateDisplay();
|
||||
timeUpdated();
|
||||
} else if (preference == mTimeZone) {
|
||||
Intent intent = new Intent();
|
||||
intent.setClass(this, ZoneList.class);
|
||||
startActivityForResult(intent, 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode,
|
||||
Intent data) {
|
||||
updateTimeAndDateDisplay();
|
||||
}
|
||||
|
||||
private void timeUpdated() {
|
||||
Intent timeChanged = new Intent(Intent.ACTION_TIME_CHANGED);
|
||||
sendBroadcast(timeChanged);
|
||||
}
|
||||
|
||||
/* Get & Set values from the system settings */
|
||||
|
||||
private boolean is24Hour() {
|
||||
String setting = Settings.System.getString(getContentResolver(),
|
||||
Settings.System.TIME_12_24);
|
||||
return HOURS_24.equals(setting);
|
||||
}
|
||||
|
||||
private void set24Hour(boolean is24Hour) {
|
||||
Settings.System.putString(getContentResolver(),
|
||||
Settings.System.TIME_12_24,
|
||||
is24Hour? HOURS_24 : HOURS_12);
|
||||
}
|
||||
|
||||
private String getDateFormat() {
|
||||
return Settings.System.getString(getContentResolver(),
|
||||
Settings.System.DATE_FORMAT);
|
||||
}
|
||||
|
||||
private boolean getAutoState() {
|
||||
try {
|
||||
return Settings.System.getInt(getContentResolver(),
|
||||
Settings.System.AUTO_TIME) > 0;
|
||||
} catch (SettingNotFoundException snfe) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void setDateFormat(String format) {
|
||||
Settings.System.putString(getContentResolver(), Settings.System.DATE_FORMAT, format);
|
||||
}
|
||||
|
||||
/* Helper routines to format timezone */
|
||||
|
||||
private String getTimeZoneText() {
|
||||
TimeZone tz = java.util.Calendar.getInstance().getTimeZone();
|
||||
boolean daylight = tz.inDaylightTime(new Date());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append(formatOffset(tz.getRawOffset() +
|
||||
(daylight ? tz.getDSTSavings() : 0))).
|
||||
append(", ").
|
||||
append(tz.getDisplayName(daylight, TimeZone.LONG));
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private char[] formatOffset(int off) {
|
||||
off = off / 1000 / 60;
|
||||
|
||||
char[] buf = new char[9];
|
||||
buf[0] = 'G';
|
||||
buf[1] = 'M';
|
||||
buf[2] = 'T';
|
||||
|
||||
if (off < 0) {
|
||||
buf[3] = '-';
|
||||
off = -off;
|
||||
} else {
|
||||
buf[3] = '+';
|
||||
}
|
||||
|
||||
int hours = off / 60;
|
||||
int minutes = off % 60;
|
||||
|
||||
buf[4] = (char) ('0' + hours / 10);
|
||||
buf[5] = (char) ('0' + hours % 10);
|
||||
|
||||
buf[6] = ':';
|
||||
|
||||
buf[7] = (char) ('0' + minutes / 10);
|
||||
buf[8] = (char) ('0' + minutes % 10);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
updateTimeAndDateDisplay();
|
||||
}
|
||||
};
|
||||
}
|
||||
41
src/com/android/settings/DateTimeSettingsSetupWizard.java
Normal file
41
src/com/android/settings/DateTimeSettingsSetupWizard.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
public class DateTimeSettingsSetupWizard extends DateTimeSettings implements OnClickListener {
|
||||
private View mNextButton;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
super.onCreate(icicle);
|
||||
setContentView(R.layout.date_time_settings_setupwizard);
|
||||
mNextButton = findViewById(R.id.next_button);
|
||||
mNextButton.setOnClickListener(this);
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
88
src/com/android/settings/DebugIntentSender.java
Normal file
88
src/com/android/settings/DebugIntentSender.java
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Button;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.text.TextUtils;
|
||||
import android.text.Spannable;
|
||||
import android.text.Selection;
|
||||
import android.net.Uri;
|
||||
|
||||
/**
|
||||
* A simple activity that provides a UI for sending intents
|
||||
*/
|
||||
public class DebugIntentSender extends Activity {
|
||||
private EditText mIntentField;
|
||||
private EditText mDataField;
|
||||
private EditText mAccountField;
|
||||
private EditText mResourceField;
|
||||
private Button mSendBroadcastButton;
|
||||
private Button mStartActivityButton;
|
||||
private View.OnClickListener mClicked = new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
if ((v == mSendBroadcastButton) ||
|
||||
(v == mStartActivityButton)) {
|
||||
String intentAction = mIntentField.getText().toString();
|
||||
String intentData = mDataField.getText().toString();
|
||||
String account = mAccountField.getText().toString();
|
||||
String resource = mResourceField.getText().toString();
|
||||
|
||||
Intent intent = new Intent(intentAction);
|
||||
if (!TextUtils.isEmpty(intentData)) {
|
||||
intent.setData(Uri.parse(intentData));
|
||||
}
|
||||
intent.putExtra("account", account);
|
||||
intent.putExtra("resource", resource);
|
||||
if (v == mSendBroadcastButton) {
|
||||
sendBroadcast(intent);
|
||||
} else {
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
setContentView(R.layout.intent_sender);
|
||||
|
||||
mIntentField = (EditText) findViewById(R.id.intent);
|
||||
mIntentField.setText(Intent.ACTION_SYNC);
|
||||
Selection.selectAll((Spannable) mIntentField.getText());
|
||||
|
||||
mDataField = (EditText) findViewById(R.id.data);
|
||||
mDataField.setBackgroundResource(android.R.drawable.editbox_background);
|
||||
|
||||
mAccountField = (EditText) findViewById(R.id.account);
|
||||
mResourceField = (EditText) findViewById(R.id.resource);
|
||||
|
||||
mSendBroadcastButton = (Button) findViewById(R.id.sendbroadcast);
|
||||
mSendBroadcastButton.setOnClickListener(mClicked);
|
||||
|
||||
mStartActivityButton = (Button) findViewById(R.id.startactivity);
|
||||
mStartActivityButton.setOnClickListener(mClicked);
|
||||
}
|
||||
}
|
||||
62
src/com/android/settings/DefaultRingtonePreference.java
Normal file
62
src/com/android/settings/DefaultRingtonePreference.java
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.preference.RingtonePreference;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
|
||||
public class DefaultRingtonePreference extends RingtonePreference {
|
||||
private static final String TAG = "DefaultRingtonePreference";
|
||||
|
||||
public DefaultRingtonePreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareRingtonePickerIntent(Intent ringtonePickerIntent) {
|
||||
super.onPrepareRingtonePickerIntent(ringtonePickerIntent);
|
||||
|
||||
/*
|
||||
* Since this preference is for choosing the default ringtone, it
|
||||
* doesn't make sense to show a 'Default' item.
|
||||
*/
|
||||
ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, false);
|
||||
|
||||
/*
|
||||
* Similarly, 'Silent' shouldn't be shown here.
|
||||
*/
|
||||
ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveRingtone(Uri ringtoneUri) {
|
||||
RingtoneManager.setActualDefaultRingtoneUri(getContext(), getRingtoneType(), ringtoneUri);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Uri onRestoreRingtone() {
|
||||
return RingtoneManager.getActualDefaultRingtoneUri(getContext(), getRingtoneType());
|
||||
}
|
||||
|
||||
}
|
||||
78
src/com/android/settings/DevelopmentSettings.java
Normal file
78
src/com/android/settings/DevelopmentSettings.java
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemProperties;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
|
||||
/*
|
||||
* Displays preferences for application developers.
|
||||
*/
|
||||
public class DevelopmentSettings extends PreferenceActivity {
|
||||
|
||||
private static final String ENABLE_ADB = "enable_adb";
|
||||
private static final String KEEP_SCREEN_ON = "keep_screen_on";
|
||||
|
||||
private CheckBoxPreference mEnableAdb;
|
||||
private CheckBoxPreference mKeepScreenOn;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
addPreferencesFromResource(R.xml.development_prefs);
|
||||
|
||||
mEnableAdb = (CheckBoxPreference) findPreference(ENABLE_ADB);
|
||||
mKeepScreenOn = (CheckBoxPreference) findPreference(KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
mEnableAdb.setChecked(Settings.System.getInt(getContentResolver(),
|
||||
Settings.System.ADB_ENABLED, 0) != 0);
|
||||
mKeepScreenOn.setChecked(Settings.System.getInt(getContentResolver(),
|
||||
Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0) != 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
|
||||
|
||||
// Those monkeys kept committing suicide, so we add this property
|
||||
// to disable this functionality
|
||||
if (!TextUtils.isEmpty(SystemProperties.get("ro.monkey"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preference == mEnableAdb) {
|
||||
Settings.System.putInt(getContentResolver(), Settings.System.ADB_ENABLED,
|
||||
mEnableAdb.isChecked() ? 1 : 0);
|
||||
} else if (preference == mKeepScreenOn) {
|
||||
Settings.System.putInt(getContentResolver(), Settings.System.STAY_ON_WHILE_PLUGGED_IN,
|
||||
mKeepScreenOn.isChecked() ? 1 : 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
134
src/com/android/settings/DeviceInfoSettings.java
Normal file
134
src/com/android/settings/DeviceInfoSettings.java
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemProperties;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class DeviceInfoSettings extends PreferenceActivity {
|
||||
|
||||
private static final String TAG = "DeviceInfoSettings";
|
||||
private static final boolean LOGD = false || Config.LOGD;
|
||||
|
||||
private static final String KEY_CONTAINER = "container";
|
||||
private static final String KEY_TEAM = "team";
|
||||
private static final String KEY_CONTRIBUTORS = "contributors";
|
||||
private static final String KEY_TERMS = "terms";
|
||||
private static final String KEY_LICENSE = "license";
|
||||
private static final String KEY_COPYRIGHT = "copyright";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
addPreferencesFromResource(R.xml.device_info_settings);
|
||||
|
||||
setSummary("firmware_version", "ro.build.version.release");
|
||||
setSummary("baseband_version", "gsm.version.baseband");
|
||||
setSummary("device_model", "ro.product.model");
|
||||
setSummary("build_number", "ro.build.description");
|
||||
findPreference("kernel_version").setSummary(getFormattedKernelVersion());
|
||||
|
||||
/*
|
||||
* Settings is a generic app and should not contain any device-specific
|
||||
* info.
|
||||
*/
|
||||
PreferenceGroup parentPreference = (PreferenceGroup) findPreference(KEY_CONTAINER);
|
||||
Utils.updatePreferenceToSpecificActivityOrRemove(this, parentPreference, KEY_TERMS,
|
||||
Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
|
||||
Utils.updatePreferenceToSpecificActivityOrRemove(this, parentPreference, KEY_LICENSE,
|
||||
Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
|
||||
Utils.updatePreferenceToSpecificActivityOrRemove(this, parentPreference, KEY_CONTRIBUTORS,
|
||||
Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
|
||||
Utils.updatePreferenceToSpecificActivityOrRemove(this, parentPreference, KEY_COPYRIGHT,
|
||||
Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
|
||||
Utils.updatePreferenceToSpecificActivityOrRemove(this, parentPreference, KEY_TEAM,
|
||||
Utils.UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY);
|
||||
}
|
||||
|
||||
private void setSummary(String preference, String property) {
|
||||
try {
|
||||
findPreference(preference).setSummary(
|
||||
SystemProperties.get(property,
|
||||
getResources().getString(R.string.device_info_default)));
|
||||
} catch (RuntimeException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private String getFormattedKernelVersion() {
|
||||
String procVersionStr;
|
||||
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new FileReader("/proc/version"), 256);
|
||||
try {
|
||||
procVersionStr = reader.readLine();
|
||||
} finally {
|
||||
reader.close();
|
||||
}
|
||||
|
||||
final String PROC_VERSION_REGEX =
|
||||
"\\w+\\s+" + /* ignore: Linux */
|
||||
"\\w+\\s+" + /* ignore: version */
|
||||
"([^\\s]+)\\s+" + /* group 1: 2.6.22-omap1 */
|
||||
"\\(([^\\s@]+(?:@[^\\s.]+)?)[^)]*\\)\\s+" + /* group 2: (xxxxxx@xxxxx.constant) */
|
||||
"\\([^)]+\\)\\s+" + /* ignore: (gcc ..) */
|
||||
"([^\\s]+)\\s+" + /* group 3: #26 */
|
||||
"(?:PREEMPT\\s+)?" + /* ignore: PREEMPT (optional) */
|
||||
"(.+)"; /* group 4: date */
|
||||
|
||||
Pattern p = Pattern.compile(PROC_VERSION_REGEX);
|
||||
Matcher m = p.matcher(procVersionStr);
|
||||
|
||||
if (!m.matches()) {
|
||||
Log.e(TAG, "Regex did not match on /proc/version: " + procVersionStr);
|
||||
return "Unavailable";
|
||||
} else if (m.groupCount() < 4) {
|
||||
Log.e(TAG, "Regex match on /proc/version only returned " + m.groupCount()
|
||||
+ " groups");
|
||||
return "Unavailable";
|
||||
} else {
|
||||
return (new StringBuilder(m.group(1)).append("\n").append(
|
||||
m.group(2)).append(" ").append(m.group(3)).append("\n")
|
||||
.append(m.group(4))).toString();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG,
|
||||
"IO Exception when getting kernel version for Device Info screen",
|
||||
e);
|
||||
|
||||
return "Unavailable";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
138
src/com/android/settings/Display.java
Normal file
138
src/com/android/settings/Display.java
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
|
||||
public class Display extends Activity implements View.OnClickListener {
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
setContentView(R.layout.display);
|
||||
|
||||
mFontSize = (Spinner) findViewById(R.id.fontSize);
|
||||
mFontSize.setOnItemSelectedListener(mFontSizeChanged);
|
||||
String[] states = new String[3];
|
||||
Resources r = getResources();
|
||||
states[0] = r.getString(R.string.small_font);
|
||||
states[1] = r.getString(R.string.medium_font);
|
||||
states[2] = r.getString(R.string.large_font);
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
|
||||
android.R.layout.simple_spinner_item, states);
|
||||
adapter.setDropDownViewResource(
|
||||
android.R.layout.simple_spinner_dropdown_item);
|
||||
mFontSize.setAdapter(adapter);
|
||||
|
||||
mPreview = (TextView) findViewById(R.id.preview);
|
||||
mPreview.setText(r.getText(R.string.font_size_preview_text));
|
||||
|
||||
Button save = (Button) findViewById(R.id.save);
|
||||
save.setText(r.getText(R.string.font_size_save));
|
||||
save.setOnClickListener(this);
|
||||
|
||||
mTextSizeTyped = new TypedValue();
|
||||
TypedArray styledAttributes =
|
||||
obtainStyledAttributes(android.R.styleable.TextView);
|
||||
styledAttributes.getValue(android.R.styleable.TextView_textSize,
|
||||
mTextSizeTyped);
|
||||
|
||||
DisplayMetrics metrics = getResources().getDisplayMetrics();
|
||||
mDisplayMetrics = new DisplayMetrics();
|
||||
mDisplayMetrics.density = metrics.density;
|
||||
mDisplayMetrics.heightPixels = metrics.heightPixels;
|
||||
mDisplayMetrics.scaledDensity = metrics.scaledDensity;
|
||||
mDisplayMetrics.widthPixels = metrics.widthPixels;
|
||||
mDisplayMetrics.xdpi = metrics.xdpi;
|
||||
mDisplayMetrics.ydpi = metrics.ydpi;
|
||||
|
||||
styledAttributes.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
try {
|
||||
mCurConfig.updateFrom(
|
||||
ActivityManagerNative.getDefault().getConfiguration());
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
if (mCurConfig.fontScale < 1) {
|
||||
mFontSize.setSelection(0);
|
||||
} else if (mCurConfig.fontScale > 1) {
|
||||
mFontSize.setSelection(2);
|
||||
} else {
|
||||
mFontSize.setSelection(1);
|
||||
}
|
||||
updateFontScale();
|
||||
}
|
||||
|
||||
private void updateFontScale() {
|
||||
mDisplayMetrics.scaledDensity = mDisplayMetrics.density *
|
||||
mCurConfig.fontScale;
|
||||
|
||||
float size = mTextSizeTyped.getDimension(mDisplayMetrics);
|
||||
mPreview.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
ActivityManagerNative.getDefault().updateConfiguration(mCurConfig);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
private Spinner.OnItemSelectedListener mFontSizeChanged
|
||||
= new Spinner.OnItemSelectedListener() {
|
||||
public void onItemSelected(android.widget.AdapterView av, View v,
|
||||
int position, long id) {
|
||||
if (position == 0) {
|
||||
mCurConfig.fontScale = .75f;
|
||||
} else if (position == 2) {
|
||||
mCurConfig.fontScale = 1.25f;
|
||||
} else {
|
||||
mCurConfig.fontScale = 1.0f;
|
||||
}
|
||||
|
||||
updateFontScale();
|
||||
}
|
||||
|
||||
public void onNothingSelected(android.widget.AdapterView av) {
|
||||
}
|
||||
};
|
||||
|
||||
private Spinner mFontSize;
|
||||
private TextView mPreview;
|
||||
private TypedValue mTextSizeTyped;
|
||||
private DisplayMetrics mDisplayMetrics;
|
||||
private Configuration mCurConfig = new Configuration();
|
||||
}
|
||||
84
src/com/android/settings/EditPinPreference.java
Normal file
84
src/com/android/settings/EditPinPreference.java
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.text.method.DigitsKeyListener;
|
||||
import android.text.method.PasswordTransformationMethod;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* TODO: Add a soft dialpad for PIN entry.
|
||||
*/
|
||||
class EditPinPreference extends EditTextPreference {
|
||||
|
||||
private boolean mDialogOpen;
|
||||
|
||||
interface OnPinEnteredListener {
|
||||
void onPinEntered(EditPinPreference preference, boolean positiveResult);
|
||||
}
|
||||
|
||||
private OnPinEnteredListener mPinListener;
|
||||
|
||||
public EditPinPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public EditPinPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public void setOnPinEnteredListener(OnPinEnteredListener listener) {
|
||||
mPinListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindDialogView(View view) {
|
||||
super.onBindDialogView(view);
|
||||
|
||||
final EditText editText = (EditText) view.findViewById(android.R.id.edit);
|
||||
|
||||
if (editText != null) {
|
||||
editText.setSingleLine(true);
|
||||
editText.setTransformationMethod(PasswordTransformationMethod.getInstance());
|
||||
editText.setKeyListener(DigitsKeyListener.getInstance());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDialogOpen() {
|
||||
return mDialogOpen;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDialogClosed(boolean positiveResult) {
|
||||
super.onDialogClosed(positiveResult);
|
||||
mDialogOpen = false;
|
||||
if (mPinListener != null) {
|
||||
mPinListener.onPinEntered(this, positiveResult);
|
||||
}
|
||||
}
|
||||
|
||||
public void showPinDialog() {
|
||||
mDialogOpen = true;
|
||||
showDialog(null);
|
||||
}
|
||||
}
|
||||
414
src/com/android/settings/InstalledAppDetails.java
Normal file
414
src/com/android/settings/InstalledAppDetails.java
Normal file
@@ -0,0 +1,414 @@
|
||||
|
||||
|
||||
/**
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import com.android.settings.R;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageDataObserver;
|
||||
import android.content.pm.IPackageStatsObserver;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageStats;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import android.content.ComponentName;
|
||||
import android.view.View;
|
||||
import android.widget.AppSecurityPermissions;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* Activity to display application information from Settings
|
||||
*
|
||||
*/
|
||||
public class InstalledAppDetails extends Activity implements View.OnClickListener, DialogInterface.OnClickListener {
|
||||
private static final String TAG="InstalledAppDetails";
|
||||
private static final int _UNKNOWN_APP=R.string.unknown;
|
||||
//wait times used for the async package manager api
|
||||
private ApplicationInfo mAppInfo;
|
||||
private Button mUninstallButton;
|
||||
private Button mActivitiesButton;
|
||||
private boolean mSysPackage;
|
||||
private boolean localLOGV=Config.LOGV || true;
|
||||
private TextView mTotalSize;
|
||||
private TextView mAppSize;
|
||||
private TextView mDataSize;
|
||||
PackageStats mSizeInfo;
|
||||
private Button mManageSpaceButton;
|
||||
private PackageManager mPm;
|
||||
private String mBStr, mKbStr, mMbStr;
|
||||
|
||||
//internal constants used in Handler
|
||||
private static final int CLEAR_USER_DATA = 1;
|
||||
private static final int OP_SUCCESSFUL = 1;
|
||||
private static final int OP_FAILED = 2;
|
||||
private static final int GET_PKG_SIZE = 2;
|
||||
private static final String ATTR_PACKAGE_STATS="PackageStats";
|
||||
|
||||
private Handler mHandler = new Handler() {
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case CLEAR_USER_DATA:
|
||||
processClearMsg(msg);
|
||||
break;
|
||||
case GET_PKG_SIZE:
|
||||
refreshSizeInfo(msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private boolean isSystemPackage() {
|
||||
if ((mAppInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class ClearUserDataObserver extends IPackageDataObserver.Stub {
|
||||
public void onRemoveCompleted(final String packageName, final boolean succeeded) {
|
||||
final Message msg = mHandler.obtainMessage(CLEAR_USER_DATA);
|
||||
msg.arg1 = succeeded?OP_SUCCESSFUL:OP_FAILED;
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
class PkgSizeObserver extends IPackageStatsObserver.Stub {
|
||||
public int idx;
|
||||
public void onGetStatsCompleted(PackageStats pStats, boolean succeeded) {
|
||||
Message msg = mHandler.obtainMessage(GET_PKG_SIZE);
|
||||
Bundle data = new Bundle();
|
||||
data.putParcelable(ATTR_PACKAGE_STATS, pStats);
|
||||
msg.setData(data);
|
||||
mHandler.sendMessage(msg);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private String getSizeStr(long size) {
|
||||
String retStr = "";
|
||||
if(size < 1024) {
|
||||
return String.valueOf(size)+mBStr;
|
||||
}
|
||||
long kb, mb, rem;
|
||||
kb = size >> 10;
|
||||
rem = size - (kb << 10);
|
||||
if(kb < 1024) {
|
||||
if(rem > 512) {
|
||||
kb++;
|
||||
}
|
||||
retStr += String.valueOf(kb)+mKbStr;
|
||||
return retStr;
|
||||
}
|
||||
mb = kb >> 10;
|
||||
if(kb >= 512) {
|
||||
//round off
|
||||
mb++;
|
||||
}
|
||||
retStr += String.valueOf(mb)+ mMbStr;
|
||||
return retStr;
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
//get package manager
|
||||
mPm = getPackageManager();
|
||||
//get application's name from intent
|
||||
Intent intent = getIntent();
|
||||
final String packageName = intent.getStringExtra(ManageApplications.APP_PKG_NAME);
|
||||
mSizeInfo = intent.getParcelableExtra(ManageApplications.APP_PKG_SIZE);
|
||||
long total = -1;
|
||||
long code = -1;
|
||||
long data = -1;
|
||||
if(mSizeInfo != null) {
|
||||
total = mSizeInfo.cacheSize+mSizeInfo.codeSize+mSizeInfo.dataSize;
|
||||
code = mSizeInfo.codeSize;
|
||||
data = mSizeInfo.dataSize+mSizeInfo.cacheSize;
|
||||
}
|
||||
String unknownStr = getString(_UNKNOWN_APP);
|
||||
mBStr = getString(R.string.b_text);
|
||||
mKbStr = getString(R.string.kb_text);
|
||||
mMbStr = getString(R.string.mb_text);
|
||||
String totalSizeStr = unknownStr;
|
||||
if(total != -1) {
|
||||
totalSizeStr = getSizeStr(total);
|
||||
}
|
||||
String appSizeStr = unknownStr;
|
||||
if(code != -1) {
|
||||
appSizeStr = getSizeStr(code);
|
||||
}
|
||||
String dataSizeStr = unknownStr;
|
||||
if(data != -1) {
|
||||
dataSizeStr = getSizeStr(data);
|
||||
}
|
||||
if(localLOGV) Log.i(TAG, "packageName:"+packageName+", total="+total+
|
||||
"code="+code+", data="+data);
|
||||
try {
|
||||
mAppInfo = mPm.getApplicationInfo(packageName, 0);
|
||||
} catch (NameNotFoundException e) {
|
||||
Throwable th = e.fillInStackTrace();
|
||||
Log.e(TAG, "Exception when retrieving package:"+packageName, e);
|
||||
displayErrorDialog(R.string.app_not_found_dlg_text, true, true);
|
||||
}
|
||||
setContentView(R.layout.installed_app_details);
|
||||
((ImageView)findViewById(R.id.app_icon)).setImageDrawable(mPm.
|
||||
getApplicationIcon(mAppInfo));
|
||||
//set application name TODO version
|
||||
CharSequence appName = mPm.getApplicationLabel(mAppInfo);
|
||||
if(appName == null) {
|
||||
appName = getString(_UNKNOWN_APP);
|
||||
}
|
||||
((TextView)findViewById(R.id.app_name)).setText(appName);
|
||||
CharSequence appDesc = mAppInfo.loadDescription(mPm);
|
||||
if(appDesc != null) {
|
||||
((TextView)findViewById(R.id.app_description)).setText(appDesc);
|
||||
}
|
||||
//TODO download str and download url
|
||||
//set values on views
|
||||
mTotalSize = (TextView)findViewById(R.id.total_size_text);
|
||||
mTotalSize.setText(totalSizeStr);
|
||||
mAppSize = (TextView)findViewById(R.id.application_size_text);
|
||||
mAppSize.setText(appSizeStr);
|
||||
mDataSize = (TextView)findViewById(R.id.data_size_text);
|
||||
mDataSize.setText(dataSizeStr);
|
||||
|
||||
mUninstallButton = ((Button)findViewById(R.id.uninstall_button));
|
||||
//determine if app is a system app
|
||||
mSysPackage = isSystemPackage();
|
||||
if(localLOGV) Log.i(TAG, "Is systemPackage "+mSysPackage);
|
||||
int btnText;
|
||||
boolean btnClickable = true;
|
||||
|
||||
if(mSysPackage) {
|
||||
//app can clear user data
|
||||
if((mAppInfo.flags & ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA)
|
||||
== ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) {
|
||||
mUninstallButton.setText(R.string.clear_user_data_text);
|
||||
//disable button if data is 0
|
||||
if(data == 0) {
|
||||
mUninstallButton.setEnabled(false);
|
||||
} else {
|
||||
//enable button
|
||||
mUninstallButton.setOnClickListener(this);
|
||||
}
|
||||
} else {
|
||||
//hide button if diableClearUserData is set
|
||||
mUninstallButton.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
mUninstallButton.setText(R.string.uninstall_text);
|
||||
mUninstallButton.setOnClickListener(this);
|
||||
}
|
||||
//clear activities
|
||||
mActivitiesButton = (Button)findViewById(R.id.clear_activities_button);
|
||||
List<ComponentName> prefActList = new ArrayList<ComponentName>();
|
||||
//intent list cannot be null. so pass empty list
|
||||
List<IntentFilter> intentList = new ArrayList<IntentFilter>();
|
||||
mPm.getPreferredActivities(intentList, prefActList, packageName);
|
||||
if(localLOGV) Log.i(TAG, "Have "+prefActList.size()+" number of activities in prefered list");
|
||||
TextView autoLaunchView = (TextView)findViewById(R.id.auto_launch);
|
||||
if(prefActList.size() <= 0) {
|
||||
//disable clear activities button
|
||||
autoLaunchView.setText(R.string.auto_launch_disable_text);
|
||||
mActivitiesButton.setEnabled(false);
|
||||
} else {
|
||||
autoLaunchView.setText(R.string.auto_launch_enable_text);
|
||||
mActivitiesButton.setOnClickListener(this);
|
||||
}
|
||||
mManageSpaceButton = (Button)findViewById(R.id.manage_space_button);
|
||||
if(mAppInfo.manageSpaceActivityName != null) {
|
||||
mManageSpaceButton.setVisibility(View.VISIBLE);
|
||||
mManageSpaceButton.setOnClickListener(this);
|
||||
}
|
||||
//security permissions section
|
||||
AppSecurityPermissions asp = new AppSecurityPermissions(this);
|
||||
PackageInfo pkgInfo;
|
||||
try {
|
||||
pkgInfo = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
|
||||
} catch (NameNotFoundException e) {
|
||||
Log.w(TAG, "Couldnt retrieve permissions for package:"+packageName);
|
||||
return;
|
||||
}
|
||||
asp.setSecurityPermissionsView(pkgInfo);
|
||||
LinearLayout securityList = (LinearLayout) findViewById(R.id.security_settings_list);
|
||||
securityList.addView(asp.getPermissionsView());
|
||||
}
|
||||
|
||||
private void displayErrorDialog(int msgId, final boolean finish, final boolean changed) {
|
||||
//display confirmation dialog
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.app_not_found_dlg_title))
|
||||
.setIcon(R.drawable.ic_dialog_alert)
|
||||
.setMessage(getString(msgId))
|
||||
.setNeutralButton(getString(R.string.dlg_ok),
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
//force to recompute changed value
|
||||
setIntentAndFinish(finish, changed);
|
||||
}
|
||||
}
|
||||
)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void setIntentAndFinish(boolean finish, boolean appChanged) {
|
||||
if(localLOGV) Log.i(TAG, "appChanged="+appChanged);
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(ManageApplications.APP_CHG, appChanged);
|
||||
setResult(ManageApplications.RESULT_OK, intent);
|
||||
mUninstallButton.setEnabled(false);
|
||||
if(finish) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Private method to handle get size info notification from observer when
|
||||
* the async operation from PackageManager is complete. The current user data
|
||||
* info has to be refreshed in the manage applications screen as well as the current screen.
|
||||
*/
|
||||
private void refreshSizeInfo(Message msg) {
|
||||
boolean changed = false;
|
||||
Intent intent = new Intent();
|
||||
PackageStats newPs = msg.getData().getParcelable(ATTR_PACKAGE_STATS);
|
||||
long newTot = newPs.cacheSize+newPs.codeSize+newPs.dataSize;
|
||||
long oldTot = mSizeInfo.cacheSize+mSizeInfo.codeSize+mSizeInfo.dataSize;
|
||||
if(newTot != oldTot) {
|
||||
mTotalSize.setText(getSizeStr(newTot));
|
||||
changed = true;
|
||||
}
|
||||
if(newPs.codeSize != mSizeInfo.codeSize) {
|
||||
mAppSize.setText(getSizeStr(newPs.codeSize));
|
||||
changed = true;
|
||||
}
|
||||
if((newPs.dataSize != mSizeInfo.dataSize) || (newPs.cacheSize != mSizeInfo.cacheSize)) {
|
||||
mDataSize.setText(getSizeStr(newPs.dataSize+newPs.cacheSize));
|
||||
changed = true;
|
||||
}
|
||||
if(changed) {
|
||||
mUninstallButton.setText(R.string.clear_user_data_text);
|
||||
mSizeInfo = newPs;
|
||||
intent.putExtra(ManageApplications.APP_PKG_SIZE, mSizeInfo);
|
||||
}
|
||||
intent.putExtra(ManageApplications.APP_CHG, changed);
|
||||
setResult(ManageApplications.RESULT_OK, intent);
|
||||
}
|
||||
|
||||
/*
|
||||
* Private method to handle clear message notification from observer when
|
||||
* the async operation from PackageManager is complete
|
||||
*/
|
||||
private void processClearMsg(Message msg) {
|
||||
int result = msg.arg1;
|
||||
String packageName = mAppInfo.packageName;
|
||||
if(result == OP_SUCCESSFUL) {
|
||||
Log.i(TAG, "Cleared user data for system package:"+packageName);
|
||||
PkgSizeObserver observer = new PkgSizeObserver();
|
||||
mPm.getPackageSizeInfo(packageName, observer);
|
||||
} else {
|
||||
mUninstallButton.setText(R.string.clear_user_data_text);
|
||||
mUninstallButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Private method to initiate clearing user data when the user clicks the clear data
|
||||
* button for a system package
|
||||
*/
|
||||
private void initiateClearUserDataForSysPkg() {
|
||||
mUninstallButton.setEnabled(false);
|
||||
//invoke uninstall or clear user data based on sysPackage
|
||||
boolean recomputeSizes = false;
|
||||
String packageName = mAppInfo.packageName;
|
||||
Log.i(TAG, "Clearing user data for system package");
|
||||
ClearUserDataObserver observer = new ClearUserDataObserver();
|
||||
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
|
||||
boolean res = am.clearApplicationUserData(packageName, observer);
|
||||
if(!res) {
|
||||
//doesnt initiate clear. some error. should not happen but just log error for now
|
||||
Log.i(TAG, "Couldnt clear application user data for package:"+packageName);
|
||||
displayErrorDialog(R.string.clear_data_failed, false, false);
|
||||
} else {
|
||||
mUninstallButton.setText(R.string.recompute_size);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Method implementing functionality of buttons clicked
|
||||
* @see android.view.View.OnClickListener#onClick(android.view.View)
|
||||
*/
|
||||
public void onClick(View v) {
|
||||
String packageName = mAppInfo.packageName;
|
||||
if(v == mUninstallButton) {
|
||||
if(mSysPackage) {
|
||||
//display confirmation dialog
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.clear_data_dlg_title))
|
||||
.setIcon(R.drawable.ic_dialog_alert)
|
||||
.setMessage(getString(R.string.clear_data_dlg_text))
|
||||
.setPositiveButton(R.string.dlg_ok, this)
|
||||
.setNegativeButton(R.string.dlg_cancel, this)
|
||||
.show();
|
||||
} else {
|
||||
//create new intent to launch Uninstaller activity
|
||||
Uri packageURI = Uri.parse("package:"+packageName);
|
||||
Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, packageURI);
|
||||
startActivity(uninstallIntent);
|
||||
setIntentAndFinish(true, false);
|
||||
}
|
||||
} else if(v == mActivitiesButton) {
|
||||
mPm.clearPackagePreferredActivities(packageName);
|
||||
mActivitiesButton.setEnabled(false);
|
||||
} else if(v == mManageSpaceButton) {
|
||||
Intent intent = new Intent(Intent.ACTION_DEFAULT);
|
||||
intent.setClassName(mAppInfo.packageName, mAppInfo.manageSpaceActivityName);
|
||||
startActivityForResult(intent, -1);
|
||||
}
|
||||
}
|
||||
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if(which == AlertDialog.BUTTON1) {
|
||||
//invoke uninstall or clear user data based on sysPackage
|
||||
initiateClearUserDataForSysPkg();
|
||||
} else {
|
||||
//cancel do nothing just retain existing screen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
81
src/com/android/settings/LanguageSettings.java
Normal file
81
src/com/android/settings/LanguageSettings.java
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.provider.Settings.System;
|
||||
|
||||
public class LanguageSettings extends PreferenceActivity {
|
||||
|
||||
private final String[] mSettingsUiKey = {
|
||||
"auto_caps",
|
||||
"auto_replace",
|
||||
"auto_punctuate",
|
||||
};
|
||||
|
||||
// Note: Order of this array should correspond to the order of the above array
|
||||
private final String[] mSettingsSystemId = {
|
||||
System.TEXT_AUTO_CAPS,
|
||||
System.TEXT_AUTO_REPLACE,
|
||||
System.TEXT_AUTO_PUNCTUATE,
|
||||
};
|
||||
|
||||
// Note: Order of this array should correspond to the order of the above array
|
||||
private final int[] mSettingsDefault = {
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
addPreferencesFromResource(R.xml.language_settings);
|
||||
|
||||
if (getAssets().getLocales().length == 1) {
|
||||
getPreferenceScreen().
|
||||
removePreference(findPreference("language_category"));
|
||||
}
|
||||
|
||||
ContentResolver resolver = getContentResolver();
|
||||
for (int i = 0; i < mSettingsUiKey.length; i++) {
|
||||
CheckBoxPreference pref = (CheckBoxPreference) findPreference(mSettingsUiKey[i]);
|
||||
pref.setChecked(System.getInt(resolver, mSettingsSystemId[i],
|
||||
mSettingsDefault[i]) > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
|
||||
for (int i = 0; i < mSettingsUiKey.length; i++) {
|
||||
if (mSettingsUiKey[i].equals(preference.getKey())) {
|
||||
System.putInt(getContentResolver(), mSettingsSystemId[i],
|
||||
((CheckBoxPreference)preference).isChecked()? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.onPreferenceTreeClick(preferenceScreen, preference);
|
||||
}
|
||||
|
||||
}
|
||||
134
src/com/android/settings/LocalePicker.java
Normal file
134
src/com/android/settings/LocalePicker.java
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.app.IActivityManager;
|
||||
import android.app.ListActivity;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
public class LocalePicker extends ListActivity {
|
||||
private static final String TAG = "LocalePicker";
|
||||
|
||||
Loc[] mLocales;
|
||||
|
||||
private static class Loc {
|
||||
String label;
|
||||
Locale locale;
|
||||
|
||||
public Loc(String label, Locale locale) {
|
||||
this.label = label;
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.label;
|
||||
}
|
||||
}
|
||||
|
||||
int getContentView() {
|
||||
return R.layout.locale_picker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
setContentView(getContentView());
|
||||
|
||||
String[] locales = getAssets().getLocales();
|
||||
final int N = locales.length;
|
||||
mLocales = new Loc[N];
|
||||
for (int i = 0; i < N; i++) {
|
||||
Locale locale = null;
|
||||
String s = locales[i];
|
||||
int len = s.length();
|
||||
if (len == 0) {
|
||||
locale = new Locale("en", "US");
|
||||
} else if (len == 2) {
|
||||
locale = new Locale(s);
|
||||
} else if (len == 5) {
|
||||
locale = new Locale(s.substring(0, 2), s.substring(3, 5));
|
||||
}
|
||||
String displayName = "";
|
||||
if (locale != null) {
|
||||
displayName = locale.getDisplayName();
|
||||
}
|
||||
if ("zz_ZZ".equals(s)) {
|
||||
displayName = "Pseudo...";
|
||||
}
|
||||
|
||||
mLocales[i] = new Loc(displayName, locale);
|
||||
}
|
||||
|
||||
int layoutId = R.layout.locale_picker_item;
|
||||
int fieldId = R.id.locale;
|
||||
ArrayAdapter<Loc> adapter = new ArrayAdapter<Loc>(this, layoutId, fieldId, mLocales);
|
||||
getListView().setAdapter(adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
getListView().requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
try {
|
||||
IActivityManager am = ActivityManagerNative.getDefault();
|
||||
Configuration config = am.getConfiguration();
|
||||
|
||||
Loc loc = mLocales[position];
|
||||
config.locale = loc.locale;
|
||||
final String language = loc.locale.getLanguage();
|
||||
final String region = loc.locale.getCountry();
|
||||
|
||||
am.updateConfiguration(config);
|
||||
|
||||
// Update the System properties
|
||||
SystemProperties.set("user.language", language);
|
||||
SystemProperties.set("user.region", region);
|
||||
// Write to file for persistence across reboots
|
||||
try {
|
||||
BufferedWriter bw = new BufferedWriter(new java.io.FileWriter(
|
||||
System.getenv("ANDROID_DATA") + "/locale"));
|
||||
bw.write(language + "_" + region);
|
||||
bw.close();
|
||||
} catch (java.io.IOException ioe) {
|
||||
Log.e(TAG,
|
||||
"Unable to persist locale. Error writing to locale file."
|
||||
+ ioe);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// Intentionally left blank
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
43
src/com/android/settings/LocalePickerInSetupWizard.java
Normal file
43
src/com/android/settings/LocalePickerInSetupWizard.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.app.IActivityManager;
|
||||
import android.app.ListActivity;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
public class LocalePickerInSetupWizard extends LocalePicker {
|
||||
|
||||
@Override
|
||||
int getContentView() {
|
||||
return R.layout.locale_picker_in_setupwizard;
|
||||
}
|
||||
|
||||
}
|
||||
616
src/com/android/settings/ManageApplications.java
Normal file
616
src/com/android/settings/ManageApplications.java
Normal file
@@ -0,0 +1,616 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import com.android.settings.R;
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageStatsObserver;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageStats;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SimpleAdapter;
|
||||
import android.widget.TextView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Activity to pick an application that will be used to display installation information and
|
||||
* options to upgrade/uninstall/delete user data for system applications.
|
||||
* Initially a compute in progress message is displayed while the application retrieves
|
||||
* the size information of installed packages which is done asynchronously through a
|
||||
* handler. Once the computation is done package resource information is retrieved
|
||||
* and then the information is displayed on the screen. All
|
||||
* messages are passed through a Handler object.
|
||||
* Known issue: There could be some ordering issues when installing/uninstalling
|
||||
* applications when the application list is being scanned.
|
||||
*/
|
||||
public class ManageApplications extends Activity implements SimpleAdapter.ViewBinder, OnItemClickListener {
|
||||
private static final String TAG = "ManageApplications";
|
||||
//Application prefix information
|
||||
public static final String APP_PKG_PREFIX="com.android.settings.";
|
||||
public static final String APP_PKG_NAME=APP_PKG_PREFIX+"ApplicationPkgName";
|
||||
public static final String APP_PKG_SIZE= APP_PKG_PREFIX+"size";
|
||||
public static final String APP_CHG=APP_PKG_PREFIX+"changed";
|
||||
|
||||
//constant value that can be used to check return code from sub activity.
|
||||
private static final int INSTALLED_APP_DETAILS = 1;
|
||||
//application attributes passed to sub activity that displays more app info
|
||||
private static final String KEY_APP_NAME = "ApplicationName";
|
||||
private static final String KEY_APP_ICON = "ApplicationIcon";
|
||||
private static final String KEY_APP_DESC = "ApplicationDescription";
|
||||
private static final String KEY_APP_SIZE= "ApplicationSize";
|
||||
//sort order that can be changed through the menu
|
||||
public static final int SORT_ORDER_ALPHA = 0;
|
||||
public static final int SORT_ORDER_SIZE = 1;
|
||||
//key and resource values used in constructing map for SimpleAdapter
|
||||
private static final String sKeys[] = new String[] { KEY_APP_NAME, KEY_APP_ICON,
|
||||
KEY_APP_DESC, KEY_APP_SIZE};
|
||||
private static final int sResourceIds[] = new int[] { R.id.app_name, R.id.app_icon,
|
||||
R.id.app_description, R.id.app_size};
|
||||
//List of ApplicationInfo objects for various applications
|
||||
private List<ApplicationInfo> mAppList;
|
||||
//SimpleAdapter used for managing items in the list
|
||||
private SimpleAdapter mAppAdapter;
|
||||
//map used to store size information which is used for displaying size information
|
||||
//in this activity as well as the subactivity. this is to avoid invoking package manager
|
||||
//api to retrieve size information
|
||||
private HashMap<String, PackageStats> mSizeMap;
|
||||
private HashMap<String, Map<String, ?> > mAppAdapterMap;
|
||||
//sort order
|
||||
private int mSortOrder = SORT_ORDER_ALPHA;
|
||||
//log information boolean
|
||||
private boolean localLOGV = Config.LOGV || false;
|
||||
private ApplicationInfo mCurrentPkg;
|
||||
private int mCurrentPkgIdx = 0;
|
||||
private static final int COMPUTE_PKG_SIZE_START = 1;
|
||||
private static final int COMPUTE_PKG_SIZE_DONE = 2;
|
||||
private static final int REMOVE_PKG=3;
|
||||
private static final int REORDER_LIST=4;
|
||||
private static final int ADD_PKG=5;
|
||||
private static final String ATTR_APP_IDX="ApplicationIndex";
|
||||
private static final String ATTR_CHAINED="Chained";
|
||||
private static final String ATTR_PKG_NAME="PackageName";
|
||||
private PkgSizeObserver mObserver;
|
||||
private PackageManager mPm;
|
||||
private PackageIntentReceiver mReceiver;
|
||||
private boolean mDoneIniting = false;
|
||||
private String mKbStr;
|
||||
private String mMbStr;
|
||||
private String mBStr;
|
||||
|
||||
/*
|
||||
* Handler class to handle messages for various operations
|
||||
*/
|
||||
private Handler mHandler = new Handler() {
|
||||
public void handleMessage(Message msg) {
|
||||
PackageStats ps;
|
||||
ApplicationInfo info;
|
||||
Bundle data;
|
||||
String pkgName;
|
||||
int idx;
|
||||
int size;
|
||||
boolean chained = false;
|
||||
data = msg.getData();
|
||||
switch (msg.what) {
|
||||
case COMPUTE_PKG_SIZE_START:
|
||||
mDoneIniting = false;
|
||||
//initialize lists
|
||||
mAppList = new ArrayList<ApplicationInfo>();
|
||||
mSizeMap = new HashMap<String, PackageStats>();
|
||||
mAppAdapterMap = new HashMap<String, Map<String, ?> >();
|
||||
//update application list from PackageManager
|
||||
mAppList = mPm.getInstalledApplications(0);
|
||||
if(mAppList.size() == 0) {
|
||||
return;
|
||||
}
|
||||
mCurrentPkgIdx = 0;
|
||||
mCurrentPkg = mAppList.get(0);
|
||||
if(localLOGV) Log.i(TAG, "Initiating compute sizes for first time");
|
||||
//register receiver
|
||||
mReceiver = new PackageIntentReceiver();
|
||||
mReceiver.registerReceiver();
|
||||
pkgName = mCurrentPkg.packageName;
|
||||
mObserver = new PkgSizeObserver(0);
|
||||
mObserver.invokeGetSizeInfo(pkgName, true);
|
||||
break;
|
||||
case COMPUTE_PKG_SIZE_DONE:
|
||||
ps = mObserver.ps;
|
||||
info = mObserver.appInfo;
|
||||
chained = data.getBoolean(ATTR_CHAINED);
|
||||
if(!mObserver.succeeded) {
|
||||
if(chained) {
|
||||
removePackageFromAppList(ps.packageName);
|
||||
} else {
|
||||
//do not go to adding phase
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
//insert size value
|
||||
mSizeMap.put(ps.packageName, ps);
|
||||
Map<String, Object> entry = createMapEntry(mPm.getApplicationLabel(info),
|
||||
mPm.getApplicationIcon(info),
|
||||
info.loadDescription(mPm),
|
||||
getSizeStr(ps));
|
||||
mAppAdapterMap.put(ps.packageName, entry);
|
||||
}
|
||||
if(chained) {
|
||||
//here app list is precomputed
|
||||
idx = data.getInt(ATTR_APP_IDX);
|
||||
//increment only if succeded
|
||||
if(mObserver.succeeded) {
|
||||
idx++;
|
||||
}
|
||||
if(idx < mAppList.size()) {
|
||||
pkgName = mAppList.get(idx).packageName;
|
||||
//increment record index and invoke getSizeInfo for next record
|
||||
mObserver.invokeGetSizeInfo(pkgName, true);
|
||||
} else {
|
||||
sortAppList();
|
||||
createListFromValues();
|
||||
mDoneIniting = true;
|
||||
}
|
||||
} else {
|
||||
//add app info object as well
|
||||
mAppList.add(info);
|
||||
sortAppList();
|
||||
size = mAppList.size();
|
||||
int i;
|
||||
for(i = 0; i < size; i++) {
|
||||
if(mAppList.get(i).packageName.equalsIgnoreCase(mCurrentPkg.packageName)) {
|
||||
if(i > mCurrentPkgIdx) {
|
||||
mCurrentPkgIdx = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
createListFromValues();
|
||||
}
|
||||
break;
|
||||
case REMOVE_PKG:
|
||||
if(!mDoneIniting) {
|
||||
//insert message again after some delay
|
||||
sendMessageToHandler(REMOVE_PKG, data, 10*1000);
|
||||
break;
|
||||
}
|
||||
pkgName = data.getString(ATTR_PKG_NAME);
|
||||
removePackageFromAppList(pkgName);
|
||||
if(mSizeMap.remove(pkgName) == null) {
|
||||
Log.i(TAG, "Coudnt remove from size map package:"+pkgName);
|
||||
}
|
||||
if(mAppAdapterMap.remove(pkgName) == null) {
|
||||
Log.i(TAG, "Coudnt remove from app adapter map package:"+pkgName);
|
||||
}
|
||||
if(mCurrentPkg.packageName.equalsIgnoreCase(pkgName)) {
|
||||
if(mCurrentPkgIdx == (mAppList.size()-1)) {
|
||||
mCurrentPkgIdx--;
|
||||
}
|
||||
mCurrentPkg = mAppList.get(mCurrentPkgIdx);
|
||||
}
|
||||
createListFromValues();
|
||||
break;
|
||||
case REORDER_LIST:
|
||||
int sortOrder = msg.arg1;
|
||||
if(sortOrder != mSortOrder) {
|
||||
mSortOrder = sortOrder;
|
||||
if(localLOGV) Log.i(TAG, "Changing sort order to "+mSortOrder);
|
||||
sortAppList();
|
||||
mCurrentPkgIdx = 0;
|
||||
mCurrentPkg = mAppList.get(mCurrentPkgIdx);
|
||||
createListFromValues();
|
||||
}
|
||||
break;
|
||||
case ADD_PKG:
|
||||
pkgName = data.getString(ATTR_PKG_NAME);
|
||||
if(!mDoneIniting) {
|
||||
//insert message again after some delay
|
||||
sendMessageToHandler(ADD_PKG, data, 10*1000);
|
||||
break;
|
||||
}
|
||||
mObserver.invokeGetSizeInfo(pkgName, false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void removePackageFromAppList(String pkgName) {
|
||||
int size = mAppList.size();
|
||||
for(int i = 0; i < size; i++) {
|
||||
if(mAppList.get(i).packageName.equalsIgnoreCase(pkgName)) {
|
||||
mAppList.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void clearMessages() {
|
||||
synchronized(mHandler) {
|
||||
mHandler.removeMessages(COMPUTE_PKG_SIZE_START);
|
||||
mHandler.removeMessages(COMPUTE_PKG_SIZE_DONE);
|
||||
mHandler.removeMessages(REMOVE_PKG);
|
||||
mHandler.removeMessages(REORDER_LIST);
|
||||
mHandler.removeMessages(ADD_PKG);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMessageToHandler(int msgId, Bundle data, long delayMillis) {
|
||||
synchronized(mHandler) {
|
||||
Message msg = mHandler.obtainMessage(msgId);
|
||||
msg.setData(data);
|
||||
if(delayMillis == 0) {
|
||||
mHandler.sendMessage(msg);
|
||||
} else {
|
||||
mHandler.sendMessageDelayed(msg, delayMillis);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMessageToHandler(int msgId, int arg1) {
|
||||
synchronized(mHandler) {
|
||||
Message msg = mHandler.obtainMessage(msgId);
|
||||
msg.arg1 = arg1;
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMessageToHandler(int msgId) {
|
||||
synchronized(mHandler) {
|
||||
mHandler.sendEmptyMessage(msgId);
|
||||
}
|
||||
}
|
||||
|
||||
class PkgSizeObserver extends IPackageStatsObserver.Stub {
|
||||
public PackageStats ps;
|
||||
public ApplicationInfo appInfo;
|
||||
public Drawable appIcon;
|
||||
public CharSequence appName;
|
||||
public CharSequence appDesc = "";
|
||||
private int mIdx = 0;
|
||||
private boolean mChained = false;
|
||||
public boolean succeeded;
|
||||
PkgSizeObserver(int i) {
|
||||
mIdx = i;
|
||||
}
|
||||
|
||||
private void getAppDetails() {
|
||||
try {
|
||||
appInfo = mPm.getApplicationInfo(ps.packageName, 0);
|
||||
} catch (NameNotFoundException e) {
|
||||
return;
|
||||
}
|
||||
appName = appInfo.loadLabel(mPm);
|
||||
appIcon = appInfo.loadIcon(mPm);
|
||||
}
|
||||
|
||||
public void onGetStatsCompleted(PackageStats pStats, boolean pSucceeded) {
|
||||
Bundle data = new Bundle();
|
||||
ps = pStats;
|
||||
succeeded = pSucceeded;
|
||||
if(mChained) {
|
||||
data.putInt(ATTR_APP_IDX, mIdx);
|
||||
if(succeeded) {
|
||||
mIdx++;
|
||||
}
|
||||
}
|
||||
data.putBoolean(ATTR_CHAINED, mChained);
|
||||
getAppDetails();
|
||||
if(localLOGV) Log.i(TAG, "onGetStatsCompleted::"+appInfo.packageName+", ("+ps.cacheSize+","+
|
||||
ps.codeSize+", "+ps.dataSize);
|
||||
sendMessageToHandler(COMPUTE_PKG_SIZE_DONE, data, 0);
|
||||
}
|
||||
|
||||
public void invokeGetSizeInfo(String packageName, boolean chained) {
|
||||
mChained = chained;
|
||||
mPm.getPackageSizeInfo(packageName, this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives notifications when applications are added/removed.
|
||||
*/
|
||||
private class PackageIntentReceiver extends BroadcastReceiver {
|
||||
void registerReceiver() {
|
||||
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
|
||||
filter.addDataScheme("package");
|
||||
ManageApplications.this.registerReceiver(this, filter);
|
||||
}
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String actionStr = intent.getAction();
|
||||
Uri data = intent.getData();
|
||||
String pkgName = data.getEncodedSchemeSpecificPart();
|
||||
if(localLOGV) Log.i(TAG, "action:"+actionStr+", for package:"+pkgName);
|
||||
updatePackageList(actionStr, pkgName);
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePackageList(String actionStr, String pkgName) {
|
||||
//technically we dont have to invoke handler since onReceive is invoked on
|
||||
//the main thread but doing it here for better clarity
|
||||
if(Intent.ACTION_PACKAGE_ADDED.equalsIgnoreCase(actionStr)) {
|
||||
Bundle data = new Bundle();
|
||||
data.putString(ATTR_PKG_NAME, pkgName);
|
||||
sendMessageToHandler(ADD_PKG, data, 0);
|
||||
} else if(Intent.ACTION_PACKAGE_REMOVED.equalsIgnoreCase(actionStr)) {
|
||||
Bundle data = new Bundle();
|
||||
data.putString(ATTR_PKG_NAME, pkgName);
|
||||
sendMessageToHandler(REMOVE_PKG, data, 0);
|
||||
} else if(Intent.ACTION_PACKAGE_CHANGED.equalsIgnoreCase(actionStr)) {
|
||||
//force adapter to draw the list again. TODO derive from SimpleAdapter
|
||||
//to avoid this
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility method to create an array of map objects from a map of map objects
|
||||
* for displaying list items to be used in SimpleAdapter.
|
||||
*/
|
||||
private void createListFromValues() {
|
||||
findViewById(R.id.center_text).setVisibility(View.GONE);
|
||||
populateAdapterList();
|
||||
mAppAdapter.setViewBinder(this);
|
||||
ListView lv= (ListView) findViewById(android.R.id.list);
|
||||
lv.setOnItemClickListener(this);
|
||||
lv.setAdapter(mAppAdapter);
|
||||
if(mCurrentPkgIdx != -1) {
|
||||
lv.setSelection(mCurrentPkgIdx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
String action = getIntent().getAction();
|
||||
if(action.equals(Intent.ACTION_MANAGE_PACKAGE_STORAGE)) {
|
||||
mSortOrder = SORT_ORDER_SIZE;
|
||||
}
|
||||
mPm = getPackageManager();
|
||||
//load strings from resources
|
||||
mBStr = getString(R.string.b_text);
|
||||
mKbStr = getString(R.string.kb_text);
|
||||
mMbStr = getString(R.string.mb_text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
setContentView(R.layout.compute_sizes);
|
||||
//clear all messages related to application list
|
||||
clearMessages();
|
||||
sendMessageToHandler(COMPUTE_PKG_SIZE_START);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
//register receiver here
|
||||
unregisterReceiver(mReceiver);
|
||||
}
|
||||
|
||||
public static class AppInfoComparator implements Comparator<ApplicationInfo> {
|
||||
public AppInfoComparator(HashMap<String, PackageStats> pSizeMap) {
|
||||
mSizeMap= pSizeMap;
|
||||
}
|
||||
|
||||
public final int compare(ApplicationInfo a, ApplicationInfo b) {
|
||||
PackageStats aps, bps;
|
||||
aps = mSizeMap.get(a.packageName);
|
||||
bps = mSizeMap.get(b.packageName);
|
||||
if (aps == null && bps == null) {
|
||||
return 0;
|
||||
} else if (aps == null) {
|
||||
return 1;
|
||||
} else if (bps == null) {
|
||||
return -1;
|
||||
}
|
||||
long atotal = aps.dataSize+aps.codeSize+aps.cacheSize;
|
||||
long btotal = bps.dataSize+bps.codeSize+bps.cacheSize;
|
||||
long ret = atotal-btotal;
|
||||
//negate result to sort in descending order
|
||||
if(ret < 0) {
|
||||
return 1;
|
||||
}
|
||||
if(ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
private HashMap<String, PackageStats> mSizeMap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Have to extract elements form map and populate a list ot be used by
|
||||
* SimpleAdapter when displaying list elements. The sort order has to follow
|
||||
* the order of elements in mAppList.
|
||||
*/
|
||||
private List<Map<String, ?>> createAdapterListFromMap() {
|
||||
//get the index from mAppInfo which gives the correct sort position
|
||||
int imax = mAppList.size();
|
||||
if(localLOGV) Log.i(TAG, "Creating new adapter list");
|
||||
List<Map<String, ?>> adapterList = new ArrayList<Map<String, ?>>();
|
||||
ApplicationInfo tmpInfo;
|
||||
for(int i = 0; i < imax; i++) {
|
||||
tmpInfo = mAppList.get(i);
|
||||
Map<String, Object>newObj = new TreeMap<String, Object>(
|
||||
mAppAdapterMap.get(tmpInfo.packageName));
|
||||
adapterList.add(newObj);
|
||||
}
|
||||
return adapterList;
|
||||
}
|
||||
|
||||
private void populateAdapterList() {
|
||||
mAppAdapter = new SimpleAdapter(this, createAdapterListFromMap(),
|
||||
R.layout.manage_applications_item, sKeys, sResourceIds);
|
||||
}
|
||||
|
||||
private String getSizeStr(PackageStats ps) {
|
||||
String retStr = "";
|
||||
//insert total size information into map to display in view
|
||||
//at this point its guaranteed that ps is not null. but checking anyway
|
||||
if(ps != null) {
|
||||
long size = ps.cacheSize+ps.codeSize+ps.dataSize;
|
||||
if(size < 1024) {
|
||||
return String.valueOf(size)+mBStr;
|
||||
}
|
||||
long kb, mb, rem;
|
||||
kb = size >> 10;
|
||||
rem = size - (kb << 10);
|
||||
if(kb < 1024) {
|
||||
if(rem > 512) {
|
||||
kb++;
|
||||
}
|
||||
retStr += String.valueOf(kb)+mKbStr;
|
||||
return retStr;
|
||||
}
|
||||
mb = kb >> 10;
|
||||
if(kb >= 512) {
|
||||
//round off
|
||||
mb++;
|
||||
}
|
||||
retStr += String.valueOf(mb)+ mMbStr;
|
||||
return retStr;
|
||||
} else {
|
||||
Log.w(TAG, "Something fishy, cannot find size info for package:"+ps.packageName);
|
||||
}
|
||||
return retStr;
|
||||
}
|
||||
|
||||
public void sortAppList() {
|
||||
// Sort application list
|
||||
if(mSortOrder == SORT_ORDER_ALPHA) {
|
||||
Collections.sort(mAppList, new ApplicationInfo.DisplayNameComparator(mPm));
|
||||
} else if(mSortOrder == SORT_ORDER_SIZE) {
|
||||
Collections.sort(mAppList, new AppInfoComparator(mSizeMap));
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> createMapEntry(CharSequence appName,
|
||||
Drawable appIcon, CharSequence appDesc, String sizeStr) {
|
||||
Map<String, Object> map = new TreeMap<String, Object>();
|
||||
map.put(KEY_APP_NAME, appName);
|
||||
//the icon cannot be null. if the application hasnt set it, the default icon is returned.
|
||||
map.put(KEY_APP_ICON, appIcon);
|
||||
if(appDesc == null) {
|
||||
appDesc="";
|
||||
}
|
||||
map.put(KEY_APP_DESC, appDesc);
|
||||
map.put(KEY_APP_SIZE, sizeStr);
|
||||
return map;
|
||||
}
|
||||
|
||||
private void startApplicationDetailsActivity(ApplicationInfo info, PackageStats ps) {
|
||||
//Create intent to start new activity
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setClass(this, InstalledAppDetails.class);
|
||||
intent.putExtra(APP_PKG_NAME, info.packageName);
|
||||
if(localLOGV) Log.i(TAG, "code="+ps.codeSize+", cache="+ps.cacheSize+", data="+ps.dataSize);
|
||||
intent.putExtra(APP_PKG_SIZE, ps);
|
||||
if(localLOGV) Log.i(TAG, "Starting sub activity to display info for app:"+info
|
||||
+" with intent:"+intent);
|
||||
//start new activity to display extended information
|
||||
if ((info.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
|
||||
}
|
||||
startActivityForResult(intent, INSTALLED_APP_DETAILS);
|
||||
}
|
||||
|
||||
public boolean setViewValue(View view, Object data, String textRepresentation) {
|
||||
if(data == null) {
|
||||
return false;
|
||||
}
|
||||
int id = view.getId();
|
||||
switch(id) {
|
||||
case R.id.app_name:
|
||||
((TextView)view).setText((String)data);
|
||||
break;
|
||||
case R.id.app_icon:
|
||||
((ImageView)view).setImageDrawable((Drawable)data);
|
||||
break;
|
||||
case R.id.app_description:
|
||||
((TextView)view).setText((String)data);
|
||||
break;
|
||||
case R.id.app_size:
|
||||
((TextView)view).setText((String)data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
menu.add(0, SORT_ORDER_ALPHA, 0, R.string.sort_order_alpha)
|
||||
.setIcon(android.R.drawable.ic_menu_sort_alphabetically);
|
||||
menu.add(0, SORT_ORDER_SIZE, 0, R.string.sort_order_size)
|
||||
.setIcon(android.R.drawable.ic_menu_sort_by_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
if(mDoneIniting) {
|
||||
menu.findItem(SORT_ORDER_ALPHA).setVisible(mSortOrder != SORT_ORDER_ALPHA);
|
||||
menu.findItem(SORT_ORDER_SIZE).setVisible(mSortOrder!= SORT_ORDER_SIZE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int menuId = item.getItemId();
|
||||
sendMessageToHandler(REORDER_LIST, menuId);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position,
|
||||
long id) {
|
||||
mCurrentPkgIdx=position;
|
||||
ApplicationInfo info = mAppList.get(position);
|
||||
mCurrentPkg = info;
|
||||
PackageStats ps = mSizeMap.get(info.packageName);
|
||||
startApplicationDetailsActivity(info, ps);
|
||||
}
|
||||
}
|
||||
205
src/com/android/settings/MasterClear.java
Normal file
205
src/com/android/settings/MasterClear.java
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.ICheckinService;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemProperties;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
/**
|
||||
* Confirm and execute a reset of the device to a clean "just out of the box"
|
||||
* state. Multiple confirmations are required: first, a general "are you sure
|
||||
* you want to do this?" prompt, followed by a keyguard pattern trace if the user
|
||||
* has defined one, followed by a final strongly-worded "THIS WILL ERASE EVERYTHING
|
||||
* ON THE PHONE" prompt. If at any time the phone is allowed to go to sleep, is
|
||||
* locked, et cetera, then the confirmation sequence is abandoned.
|
||||
*/
|
||||
public class MasterClear extends Activity {
|
||||
|
||||
private static final int KEYGUARD_REQUEST = 55;
|
||||
|
||||
private LayoutInflater mInflater;
|
||||
private LockPatternUtils mLockUtils;
|
||||
|
||||
private View mInitialView;
|
||||
private Button mInitiateButton;
|
||||
|
||||
private View mFinalView;
|
||||
private Button mFinalButton;
|
||||
|
||||
/**
|
||||
* The user has gone through the multiple confirmation, so now we go ahead
|
||||
* and invoke the Checkin Service to reset the device to its factory-default
|
||||
* state (rebooting in the process).
|
||||
*/
|
||||
private Button.OnClickListener mFinalClickListener = new Button.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
|
||||
// Those monkeys kept committing suicide, so we add this property
|
||||
// to disable going through with the master clear
|
||||
if (!TextUtils.isEmpty(SystemProperties.get("ro.monkey"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
ICheckinService service =
|
||||
ICheckinService.Stub.asInterface(ServiceManager.getService("checkin"));
|
||||
if (service != null) {
|
||||
try {
|
||||
// This RPC should never return
|
||||
service.masterClear();
|
||||
} catch (android.os.RemoteException e) {
|
||||
// Intentionally blank - there's nothing we can do here
|
||||
Log.w("MasterClear", "Unable to invoke ICheckinService.masterClear()");
|
||||
}
|
||||
} else {
|
||||
Log.w("MasterClear", "Unable to locate ICheckinService");
|
||||
}
|
||||
|
||||
/* If we reach this point, the master clear didn't happen -- the
|
||||
* service might have been unregistered with the ServiceManager,
|
||||
* the RPC might have thrown an exception, or for some reason
|
||||
* the implementation of masterClear() may have returned instead
|
||||
* of resetting the device.
|
||||
*/
|
||||
new AlertDialog.Builder(MasterClear.this)
|
||||
.setMessage(getText(R.string.master_clear_failed))
|
||||
.setPositiveButton(getText(android.R.string.ok), null)
|
||||
.show();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Keyguard validation is run using the standard {@link ConfirmLockPattern}
|
||||
* component as a subactivity
|
||||
*/
|
||||
private void runKeyguardConfirmation() {
|
||||
final Intent intent = new Intent();
|
||||
intent.setClassName("com.android.settings",
|
||||
"com.android.settings.ConfirmLockPattern");
|
||||
// supply header and footer text in the intent
|
||||
intent.putExtra(ConfirmLockPattern.HEADER_TEXT,
|
||||
getText(R.string.master_clear_gesture_prompt));
|
||||
intent.putExtra(ConfirmLockPattern.FOOTER_TEXT,
|
||||
getText(R.string.master_clear_gesture_explanation));
|
||||
startActivityForResult(intent, KEYGUARD_REQUEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (requestCode != KEYGUARD_REQUEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the user entered a valid keyguard trace, present the final
|
||||
// confirmation prompt; otherwise, go back to the initial state.
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
establishFinalConfirmationState();
|
||||
} else {
|
||||
establishInitialState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user clicks to begin the reset sequence, we next require a
|
||||
* keyguard confirmation if the user has currently enabled one. If there
|
||||
* is no keyguard available, we simply go to the final confirmation prompt.
|
||||
*/
|
||||
private Button.OnClickListener mInitiateListener = new Button.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
if (mLockUtils.isLockPatternEnabled()) {
|
||||
runKeyguardConfirmation();
|
||||
} else {
|
||||
establishFinalConfirmationState();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Configure the UI for the final confirmation interaction
|
||||
*/
|
||||
private void establishFinalConfirmationState() {
|
||||
if (mFinalView == null) {
|
||||
mFinalView = mInflater.inflate(R.layout.master_clear_final, null);
|
||||
mFinalButton =
|
||||
(Button) mFinalView.findViewById(R.id.execute_master_clear);
|
||||
mFinalButton.setOnClickListener(mFinalClickListener);
|
||||
}
|
||||
|
||||
setContentView(mFinalView);
|
||||
}
|
||||
|
||||
/**
|
||||
* In its initial state, the activity presents a button for the user to
|
||||
* click in order to initiate a confirmation sequence. This method is
|
||||
* called from various other points in the code to reset the activity to
|
||||
* this base state.
|
||||
*
|
||||
* <p>Reinflating views from resources is expensive and prevents us from
|
||||
* caching widget pointers, so we use a single-inflate pattern: we lazy-
|
||||
* inflate each view, caching all of the widget pointers we'll need at the
|
||||
* time, then simply reuse the inflated views directly whenever we need
|
||||
* to change contents.
|
||||
*/
|
||||
private void establishInitialState() {
|
||||
if (mInitialView == null) {
|
||||
mInitialView = mInflater.inflate(R.layout.master_clear_primary, null);
|
||||
mInitiateButton =
|
||||
(Button) mInitialView.findViewById(R.id.initiate_master_clear);
|
||||
mInitiateButton.setOnClickListener(mInitiateListener);
|
||||
}
|
||||
|
||||
setContentView(mInitialView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedState) {
|
||||
super.onCreate(savedState);
|
||||
|
||||
mInitialView = null;
|
||||
mFinalView = null;
|
||||
mInflater = LayoutInflater.from(this);
|
||||
mLockUtils = new LockPatternUtils(getContentResolver());
|
||||
|
||||
establishInitialState();
|
||||
}
|
||||
|
||||
/** Abandon all progress through the confirmation sequence by returning
|
||||
* to the initial view any time the activity is interrupted (e.g. by
|
||||
* idle timeout).
|
||||
*/
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
establishInitialState();
|
||||
}
|
||||
|
||||
}
|
||||
55
src/com/android/settings/ProgressCategory.java
Normal file
55
src/com/android/settings/ProgressCategory.java
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ProgressCategory extends PreferenceCategory {
|
||||
|
||||
private boolean mProgress = false;
|
||||
|
||||
public ProgressCategory(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setLayoutResource(R.layout.preference_progress_category);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindView(View view) {
|
||||
super.onBindView(view);
|
||||
View textView = view.findViewById(R.id.scanning_text);
|
||||
View progressBar = view.findViewById(R.id.scanning_progress);
|
||||
|
||||
int visibility = mProgress ? View.VISIBLE : View.INVISIBLE;
|
||||
textView.setVisibility(visibility);
|
||||
progressBar.setVisibility(visibility);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn on/off the progress indicator and text on the right.
|
||||
* @param progressOn whether or not the progress should be displayed
|
||||
*/
|
||||
public void setProgress(boolean progressOn) {
|
||||
mProgress = progressOn;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
260
src/com/android/settings/ProxySelector.java
Normal file
260
src/com/android/settings/ProxySelector.java
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Intent;
|
||||
import android.net.Proxy;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.text.Selection;
|
||||
import android.text.Spannable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.View.OnFocusChangeListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* To start the Proxy Selector activity, create the following intent.
|
||||
*
|
||||
* <code>
|
||||
* Intent intent = new Intent();
|
||||
* intent.setClassName("com.android.browser.ProxySelector");
|
||||
* startActivity(intent);
|
||||
* </code>
|
||||
*
|
||||
* you can add extra options to the intent by using
|
||||
*
|
||||
* <code>
|
||||
* intent.putExtra(key, value);
|
||||
* </code>
|
||||
*
|
||||
* the extra options are:
|
||||
*
|
||||
* button-label: a string label to display for the okay button
|
||||
* title: the title of the window
|
||||
* error-text: If not null, will be used as the label of the error message.
|
||||
*/
|
||||
public class ProxySelector extends Activity
|
||||
{
|
||||
private final static String LOGTAG = "Settings";
|
||||
|
||||
EditText mHostnameField;
|
||||
EditText mPortField;
|
||||
Button mOKButton;
|
||||
|
||||
// Matches blank input, ips, and domain names
|
||||
private static final String HOSTNAME_REGEXP = "^$|^[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*(\\.[a-zA-Z0-9]+(\\-[a-zA-Z0-9]+)*)*$";
|
||||
private static final Pattern HOSTNAME_PATTERN;
|
||||
static {
|
||||
HOSTNAME_PATTERN = Pattern.compile(HOSTNAME_REGEXP);
|
||||
}
|
||||
|
||||
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
if (android.util.Config.LOGV) Log.v(LOGTAG, "[ProxySelector] onStart");
|
||||
|
||||
setContentView(R.layout.proxy);
|
||||
initView();
|
||||
populateFields(false);
|
||||
}
|
||||
|
||||
protected void showError(int error) {
|
||||
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.proxy_error)
|
||||
.setMessage(error)
|
||||
.setPositiveButton(R.string.proxy_error_dismiss, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
void initView() {
|
||||
|
||||
mHostnameField = (EditText)findViewById(R.id.hostname);
|
||||
mHostnameField.setOnFocusChangeListener(mOnFocusChangeHandler);
|
||||
|
||||
mPortField = (EditText)findViewById(R.id.port);
|
||||
mPortField.setOnClickListener(mOKHandler);
|
||||
mPortField.setOnFocusChangeListener(mOnFocusChangeHandler);
|
||||
|
||||
mOKButton = (Button)findViewById(R.id.action);
|
||||
mOKButton.setOnClickListener(mOKHandler);
|
||||
|
||||
Button b = (Button)findViewById(R.id.clear);
|
||||
b.setOnClickListener(mClearHandler);
|
||||
|
||||
b = (Button)findViewById(R.id.defaultView);
|
||||
b.setOnClickListener(mDefaultHandler);
|
||||
}
|
||||
|
||||
void populateFields(boolean useDefault) {
|
||||
String hostname = null;
|
||||
int port = -1;
|
||||
if (useDefault) {
|
||||
// Use the default proxy settings provided by the carrier
|
||||
hostname = Proxy.getDefaultHost();
|
||||
port = Proxy.getDefaultPort();
|
||||
} else {
|
||||
// Use the last setting given by the user
|
||||
hostname = Proxy.getHost(this);
|
||||
port = Proxy.getPort(this);
|
||||
}
|
||||
|
||||
if (hostname == null) {
|
||||
hostname = "";
|
||||
}
|
||||
|
||||
mHostnameField.setText(hostname);
|
||||
|
||||
String portStr = port == -1 ? "" : Integer.toString(port);
|
||||
mPortField.setText(portStr);
|
||||
|
||||
Intent intent = getIntent();
|
||||
|
||||
String buttonLabel = intent.getStringExtra("button-label");
|
||||
if (!TextUtils.isEmpty(buttonLabel)) {
|
||||
mOKButton.setText(buttonLabel);
|
||||
}
|
||||
|
||||
String title = intent.getStringExtra("title");
|
||||
if (!TextUtils.isEmpty(title)) {
|
||||
setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* validate syntax of hostname and port entries
|
||||
* @return 0 on success, string resource ID on failure
|
||||
*/
|
||||
int validate(String hostname, String port) {
|
||||
Matcher match = HOSTNAME_PATTERN.matcher(hostname);
|
||||
|
||||
if (!match.matches()) return R.string.proxy_error_invalid_host;
|
||||
|
||||
if (hostname.length() > 0 && port.length() == 0) {
|
||||
return R.string.proxy_error_empty_port;
|
||||
}
|
||||
|
||||
if (port.length() > 0) {
|
||||
if (hostname.length() == 0) {
|
||||
return R.string.proxy_error_empty_host_set_port;
|
||||
}
|
||||
int portVal = -1;
|
||||
try {
|
||||
portVal = Integer.parseInt(port);
|
||||
} catch (NumberFormatException ex) {
|
||||
return R.string.proxy_error_invalid_port;
|
||||
}
|
||||
if (portVal <= 0 || portVal > 0xFFFF) {
|
||||
return R.string.proxy_error_invalid_port;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true on success, false if the user must correct something
|
||||
*/
|
||||
boolean saveToDb() {
|
||||
|
||||
String hostname = mHostnameField.getText().toString().trim();
|
||||
String portStr = mPortField.getText().toString().trim();
|
||||
int port = -1;
|
||||
|
||||
int result = validate(hostname, portStr);
|
||||
if (result > 0) {
|
||||
showError(result);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (portStr.length() > 0) {
|
||||
try {
|
||||
port = Integer.parseInt(portStr);
|
||||
} catch (NumberFormatException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: The best solution would be to make a better UI that would
|
||||
// disable editing of the text boxes if the user chooses to use the
|
||||
// default settings. i.e. checking a box to always use the default
|
||||
// carrier. http:/b/issue?id=756480
|
||||
// FIXME: This currently will not work if the default host is blank and
|
||||
// the user has cleared the input boxes in order to not use a proxy.
|
||||
// This is a UI problem and can be solved with some better form
|
||||
// controls.
|
||||
// FIXME: If the user types in a proxy that matches the default, should
|
||||
// we keep that setting? Can be fixed with a new UI.
|
||||
ContentResolver res = getContentResolver();
|
||||
if (hostname.equals(Proxy.getDefaultHost())
|
||||
&& port == Proxy.getDefaultPort()) {
|
||||
// If the user hit the default button and didn't change any of
|
||||
// the input boxes, treat it as if the user has not specified a
|
||||
// proxy.
|
||||
hostname = null;
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(hostname)) {
|
||||
hostname += ':' + portStr;
|
||||
}
|
||||
Settings.System.putString(res, Settings.System.HTTP_PROXY, hostname);
|
||||
sendBroadcast(new Intent(Proxy.PROXY_CHANGE_ACTION));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
OnClickListener mOKHandler = new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
if (saveToDb()) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
OnClickListener mClearHandler = new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
mHostnameField.setText("");
|
||||
mPortField.setText("");
|
||||
}
|
||||
};
|
||||
|
||||
OnClickListener mDefaultHandler = new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
populateFields(true);
|
||||
}
|
||||
};
|
||||
|
||||
OnFocusChangeListener mOnFocusChangeHandler = new OnFocusChangeListener() {
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (hasFocus) {
|
||||
TextView textView = (TextView) v;
|
||||
Selection.selectAll((Spannable) textView.getText());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
1168
src/com/android/settings/RadioInfo.java
Normal file
1168
src/com/android/settings/RadioInfo.java
Normal file
File diff suppressed because it is too large
Load Diff
45
src/com/android/settings/SdCardErrorReceiver.java
Normal file
45
src/com/android/settings/SdCardErrorReceiver.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
||||
/**
|
||||
* Glue class: connects AlarmAlert IntentReceiver to AlarmAlert
|
||||
* activity. Passes through Alarm ID.
|
||||
*/
|
||||
public class SdCardErrorReceiver extends BroadcastReceiver {
|
||||
|
||||
private static final String TAG = "SdCardErrorReceiver";
|
||||
|
||||
@Override public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
final int duration = 3500;
|
||||
if (action.equals(Intent.ACTION_MEDIA_BAD_REMOVAL)) {
|
||||
Toast.makeText(context, R.string.sdcard_removal_alert_title, duration).show();
|
||||
} else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTABLE)) {
|
||||
Toast.makeText(context, R.string.sdcard_unmountable_alert_title, duration).show();
|
||||
} else {
|
||||
Log.e(TAG, "unknown intent");
|
||||
}
|
||||
}
|
||||
}
|
||||
70
src/com/android/settings/SdCardIntentReceiver.java
Normal file
70
src/com/android/settings/SdCardIntentReceiver.java
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SdCardIntentReceiver extends BroadcastReceiver {
|
||||
|
||||
private static final int SDCARD_STATUS = 1;
|
||||
private static final String TAG = "SdCardIntentReceiver";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
NotificationManager nm = (NotificationManager) context
|
||||
.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
String action = intent.getAction();
|
||||
if (Config.LOGD) Log.d(TAG, "onReceiveIntent " + action);
|
||||
|
||||
if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {
|
||||
nm.cancel(SDCARD_STATUS);
|
||||
|
||||
Intent statusIntent = new Intent(Intent.ACTION_MAIN, null);
|
||||
statusIntent.setClass(context, SdCardSettings.class);
|
||||
nm.notify(SDCARD_STATUS, new Notification(context,
|
||||
android.R.drawable.stat_notify_sdcard,
|
||||
null,
|
||||
System.currentTimeMillis(),
|
||||
context.getText(R.string.sdcard_setting),
|
||||
null,
|
||||
statusIntent));
|
||||
} else if (action.equals(Intent.ACTION_MEDIA_REMOVED)) {
|
||||
nm.cancel(SDCARD_STATUS);
|
||||
} else if (action.equals(Intent.ACTION_MEDIA_SHARED)) {
|
||||
nm.cancel(SDCARD_STATUS);
|
||||
|
||||
Intent statusIntent = new Intent(Intent.ACTION_MAIN, null);
|
||||
statusIntent.setClass(context, SdCardSettings.class);
|
||||
nm.notify(SDCARD_STATUS, new Notification(context,
|
||||
android.R.drawable.stat_notify_sdcard_usb,
|
||||
null,
|
||||
System.currentTimeMillis(),
|
||||
"SD Card",
|
||||
null,
|
||||
statusIntent));
|
||||
}
|
||||
}
|
||||
}
|
||||
218
src/com/android/settings/SdCardSettings.java
Normal file
218
src/com/android/settings/SdCardSettings.java
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.Environment;
|
||||
import android.os.IMountService;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.StatFs;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
public class SdCardSettings extends Activity
|
||||
{
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
setContentView(R.layout.sdcard_settings_screen);
|
||||
|
||||
mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
|
||||
|
||||
mRemovedLayout = findViewById(R.id.removed);
|
||||
mMountedLayout = findViewById(R.id.mounted);
|
||||
mUnmountedLayout = findViewById(R.id.unmounted);
|
||||
mScanningLayout = findViewById(R.id.scanning);
|
||||
mSharedLayout = findViewById(R.id.shared);
|
||||
mBadRemovalLayout = findViewById(R.id.bad_removal);
|
||||
mReadOnlyStatus = findViewById(R.id.read_only);
|
||||
|
||||
mMassStorage = (CheckBox)findViewById(R.id.mass_storage);
|
||||
mMassStorage.setOnClickListener(mMassStorageListener);
|
||||
|
||||
Button unmountButton = (Button)findViewById(R.id.sdcard_unmount);
|
||||
unmountButton.setOnClickListener(mUnmountButtonHandler);
|
||||
|
||||
mTotalSize = (TextView)findViewById(R.id.total);
|
||||
mUsedSize = (TextView)findViewById(R.id.used);
|
||||
mAvailableSize = (TextView)findViewById(R.id.available);
|
||||
|
||||
// install an intent filter to receive SD card related events.
|
||||
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_REMOVED);
|
||||
intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
|
||||
intentFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
|
||||
intentFilter.addAction(Intent.ACTION_MEDIA_SHARED);
|
||||
intentFilter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
|
||||
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
|
||||
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
|
||||
intentFilter.addDataScheme("file");
|
||||
registerReceiver(mReceiver, intentFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
update();
|
||||
}
|
||||
|
||||
private void setLayout(View layout) {
|
||||
mRemovedLayout.setVisibility(layout == mRemovedLayout ? View.VISIBLE : View.GONE);
|
||||
mMountedLayout.setVisibility(layout == mMountedLayout ? View.VISIBLE : View.GONE);
|
||||
mUnmountedLayout.setVisibility(layout == mUnmountedLayout ? View.VISIBLE : View.GONE);
|
||||
mScanningLayout.setVisibility(layout == mScanningLayout ? View.VISIBLE : View.GONE);
|
||||
mSharedLayout.setVisibility(layout == mSharedLayout ? View.VISIBLE : View.GONE);
|
||||
mBadRemovalLayout.setVisibility(layout == mBadRemovalLayout ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private void update() {
|
||||
try {
|
||||
mMassStorage.setChecked(mMountService.getMassStorageEnabled());
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
|
||||
String scanVolume = null; // this no longer exists: SystemProperties.get(MediaScanner.CURRENT_VOLUME_PROPERTY, "");
|
||||
boolean scanning = "external".equals(scanVolume);
|
||||
|
||||
if (scanning) {
|
||||
setLayout(mScanningLayout);
|
||||
} else {
|
||||
String status = Environment.getExternalStorageState();
|
||||
boolean readOnly = false;
|
||||
|
||||
if (status.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
|
||||
status = Environment.MEDIA_MOUNTED;
|
||||
readOnly = true;
|
||||
}
|
||||
|
||||
if (status.equals(Environment.MEDIA_MOUNTED)) {
|
||||
try {
|
||||
File path = Environment.getExternalStorageDirectory();
|
||||
StatFs stat = new StatFs(path.getPath());
|
||||
long blockSize = stat.getBlockSize();
|
||||
long totalBlocks = stat.getBlockCount();
|
||||
long availableBlocks = stat.getAvailableBlocks();
|
||||
|
||||
mTotalSize.setText(formatSize(totalBlocks * blockSize));
|
||||
mUsedSize.setText(formatSize((totalBlocks - availableBlocks) * blockSize));
|
||||
mAvailableSize.setText(formatSize(availableBlocks * blockSize));
|
||||
} catch (IllegalArgumentException e) {
|
||||
// this can occur if the SD card is removed, but we haven't received the
|
||||
// ACTION_MEDIA_REMOVED Intent yet.
|
||||
status = Environment.MEDIA_REMOVED;
|
||||
}
|
||||
|
||||
mReadOnlyStatus.setVisibility(readOnly ? View.VISIBLE : View.GONE);
|
||||
setLayout(mMountedLayout);
|
||||
} else if (status.equals(Environment.MEDIA_UNMOUNTED)) {
|
||||
setLayout(mUnmountedLayout);
|
||||
} else if (status.equals(Environment.MEDIA_REMOVED)) {
|
||||
setLayout(mRemovedLayout);
|
||||
} else if (status.equals(Environment.MEDIA_SHARED)) {
|
||||
setLayout(mSharedLayout);
|
||||
} else if (status.equals(Environment.MEDIA_BAD_REMOVAL)) {
|
||||
setLayout(mBadRemovalLayout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String formatSize(long size) {
|
||||
String suffix = null;
|
||||
|
||||
// add K or M suffix if size is greater than 1K or 1M
|
||||
if (size >= 1024) {
|
||||
suffix = "K";
|
||||
size /= 1024;
|
||||
if (size >= 1024) {
|
||||
suffix = "M";
|
||||
size /= 1024;
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder resultBuffer = new StringBuilder(Long.toString(size));
|
||||
|
||||
int commaOffset = resultBuffer.length() - 3;
|
||||
while (commaOffset > 0) {
|
||||
resultBuffer.insert(commaOffset, ',');
|
||||
commaOffset -= 3;
|
||||
}
|
||||
|
||||
if (suffix != null)
|
||||
resultBuffer.append(suffix);
|
||||
return resultBuffer.toString();
|
||||
}
|
||||
|
||||
OnClickListener mMassStorageListener = new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
mMountService.setMassStorageEnabled(mMassStorage.isChecked());
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
update();
|
||||
}
|
||||
};
|
||||
|
||||
OnClickListener mUnmountButtonHandler = new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
mMountService.unmountMedia(Environment.getExternalStorageDirectory().toString());
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private int mStatus;
|
||||
private IMountService mMountService;
|
||||
|
||||
private CheckBox mMassStorage;
|
||||
|
||||
private TextView mTotalSize;
|
||||
private TextView mUsedSize;
|
||||
private TextView mAvailableSize;
|
||||
|
||||
private View mRemovedLayout;
|
||||
private View mMountedLayout;
|
||||
private View mUnmountedLayout;
|
||||
private View mScanningLayout;
|
||||
private View mSharedLayout;
|
||||
private View mBadRemovalLayout;
|
||||
private View mReadOnlyStatus;
|
||||
}
|
||||
281
src/com/android/settings/SecuritySettings.java
Normal file
281
src/com/android/settings/SecuritySettings.java
Normal file
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.location.LocationManager;
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.provider.Settings;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
|
||||
/**
|
||||
* Gesture lock pattern settings.
|
||||
*/
|
||||
public class SecuritySettings extends PreferenceActivity
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
// Lock Settings
|
||||
|
||||
private static final String KEY_LOCK_ENABLED = "lockenabled";
|
||||
private static final String KEY_VISIBLE_PATTERN = "visiblepattern";
|
||||
private static final int CONFIRM_PATTERN_REQUEST_CODE = 55;
|
||||
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
private CheckBoxPreference mLockEnabled;
|
||||
private CheckBoxPreference mVisiblePattern;
|
||||
private Preference mChoosePattern;
|
||||
|
||||
private CheckBoxPreference mShowPassword;
|
||||
|
||||
// Location Settings
|
||||
|
||||
private static final String LOCATION_NETWORK = "location_network";
|
||||
private static final String LOCATION_GPS = "location_gps";
|
||||
|
||||
private CheckBoxPreference mNetwork;
|
||||
private CheckBoxPreference mGps;
|
||||
private LocationManager mLocationManager;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
addPreferencesFromResource(R.xml.security_settings);
|
||||
|
||||
mLockPatternUtils = new LockPatternUtils(getContentResolver());
|
||||
|
||||
createPreferenceHierarchy();
|
||||
|
||||
// Get the available location providers
|
||||
mLocationManager = (LocationManager)
|
||||
getSystemService(Context.LOCATION_SERVICE);
|
||||
|
||||
mNetwork = (CheckBoxPreference) getPreferenceScreen().findPreference(LOCATION_NETWORK);
|
||||
mGps = (CheckBoxPreference) getPreferenceScreen().findPreference(LOCATION_GPS);
|
||||
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
|
||||
updateToggles();
|
||||
}
|
||||
|
||||
private PreferenceScreen createPreferenceHierarchy() {
|
||||
// Root
|
||||
PreferenceScreen root = this.getPreferenceScreen();
|
||||
|
||||
// Inline preferences
|
||||
PreferenceCategory inlinePrefCat = new PreferenceCategory(this);
|
||||
inlinePrefCat.setTitle(R.string.lock_settings_title);
|
||||
root.addPreference(inlinePrefCat);
|
||||
|
||||
// autolock toggle
|
||||
mLockEnabled = new LockEnabledPref(this);
|
||||
mLockEnabled.setTitle(R.string.lockpattern_settings_enable_title);
|
||||
mLockEnabled.setSummary(R.string.lockpattern_settings_enable_summary);
|
||||
mLockEnabled.setKey(KEY_LOCK_ENABLED);
|
||||
inlinePrefCat.addPreference(mLockEnabled);
|
||||
|
||||
// visible pattern
|
||||
mVisiblePattern = new CheckBoxPreference(this);
|
||||
mVisiblePattern.setKey(KEY_VISIBLE_PATTERN);
|
||||
mVisiblePattern.setTitle(R.string.lockpattern_settings_enable_visible_pattern_title);
|
||||
inlinePrefCat.addPreference(mVisiblePattern);
|
||||
|
||||
// change pattern lock
|
||||
Intent intent = new Intent();
|
||||
intent.setClassName("com.android.settings",
|
||||
"com.android.settings.ChooseLockPatternTutorial");
|
||||
mChoosePattern = getPreferenceManager().createPreferenceScreen(this);
|
||||
mChoosePattern.setIntent(intent);
|
||||
inlinePrefCat.addPreference(mChoosePattern);
|
||||
|
||||
PreferenceScreen simLockPreferences = getPreferenceManager()
|
||||
.createPreferenceScreen(this);
|
||||
simLockPreferences.setTitle(R.string.sim_lock_settings_category);
|
||||
// Intent to launch SIM lock settings
|
||||
intent = new Intent();
|
||||
intent.setClassName("com.android.settings", "com.android.settings.SimLockSettings");
|
||||
simLockPreferences.setIntent(intent);
|
||||
|
||||
PreferenceCategory simLockCat = new PreferenceCategory(this);
|
||||
simLockCat.setTitle(R.string.sim_lock_settings_title);
|
||||
root.addPreference(simLockCat);
|
||||
simLockCat.addPreference(simLockPreferences);
|
||||
|
||||
// Passwords
|
||||
PreferenceCategory passwordsCat = new PreferenceCategory(this);
|
||||
passwordsCat.setTitle(R.string.security_passwords_title);
|
||||
root.addPreference(passwordsCat);
|
||||
|
||||
CheckBoxPreference showPassword = mShowPassword = new CheckBoxPreference(this);
|
||||
showPassword.setKey("show_password");
|
||||
showPassword.setTitle(R.string.show_password);
|
||||
showPassword.setSummary(R.string.show_password_summary);
|
||||
showPassword.setPersistent(false);
|
||||
passwordsCat.addPreference(showPassword);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
boolean patternExists = mLockPatternUtils.savedPatternExists();
|
||||
mLockEnabled.setEnabled(patternExists);
|
||||
mVisiblePattern.setEnabled(patternExists);
|
||||
|
||||
mLockEnabled.setChecked(mLockPatternUtils.isLockPatternEnabled());
|
||||
mVisiblePattern.setChecked(mLockPatternUtils.isVisiblePatternEnabled());
|
||||
|
||||
int chooseStringRes = mLockPatternUtils.savedPatternExists() ?
|
||||
R.string.lockpattern_settings_change_lock_pattern :
|
||||
R.string.lockpattern_settings_choose_lock_pattern;
|
||||
mChoosePattern.setTitle(chooseStringRes);
|
||||
|
||||
mShowPassword
|
||||
.setChecked(Settings.System.getInt(getContentResolver(),
|
||||
Settings.System.TEXT_SHOW_PASSWORD, 1) != 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
|
||||
Preference preference) {
|
||||
final String key = preference.getKey();
|
||||
|
||||
if (KEY_LOCK_ENABLED.equals(key)) {
|
||||
mLockPatternUtils.setLockPatternEnabled(isToggled(preference));
|
||||
} else if (KEY_VISIBLE_PATTERN.equals(key)) {
|
||||
mLockPatternUtils.setVisiblePatternEnabled(isToggled(preference));
|
||||
} else if (preference == mShowPassword) {
|
||||
Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
|
||||
mShowPassword.isChecked() ? 1 : 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates toggles for each available location provider
|
||||
*/
|
||||
private void updateToggles() {
|
||||
String providers = getAllowedProviders();
|
||||
mNetwork.setChecked(providers.contains(LocationManager.NETWORK_PROVIDER));
|
||||
mGps.setChecked(providers.contains(LocationManager.GPS_PROVIDER));
|
||||
}
|
||||
|
||||
private void updateProviders() {
|
||||
String preferredProviders = "";
|
||||
if (mNetwork.isChecked()) {
|
||||
preferredProviders += LocationManager.NETWORK_PROVIDER;
|
||||
}
|
||||
if (mGps.isChecked()) {
|
||||
preferredProviders += "," + LocationManager.GPS_PROVIDER;
|
||||
}
|
||||
setProviders(preferredProviders);
|
||||
}
|
||||
|
||||
private void setProviders(String providers) {
|
||||
// Update the system setting LOCATION_PROVIDERS_ALLOWED
|
||||
Settings.System.putString(getContentResolver(),
|
||||
Settings.System.LOCATION_PROVIDERS_ALLOWED, providers);
|
||||
if (Config.LOGV) {
|
||||
Log.v("Location Accuracy", "Setting LOCATION_PROVIDERS_ALLOWED = " + providers);
|
||||
}
|
||||
// Inform the location manager about the changes
|
||||
mLocationManager.updateProviders();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string containing a list of providers that have been enabled for use
|
||||
*/
|
||||
private String getAllowedProviders() {
|
||||
String allowedProviders =
|
||||
Settings.System.getString(getContentResolver(),
|
||||
Settings.System.LOCATION_PROVIDERS_ALLOWED);
|
||||
if (allowedProviders == null) {
|
||||
allowedProviders = "";
|
||||
}
|
||||
return allowedProviders;
|
||||
}
|
||||
|
||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||
if (LOCATION_NETWORK.equals(key) || LOCATION_GPS.equals(key)) {
|
||||
updateProviders();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isToggled(Preference pref) {
|
||||
return ((CheckBoxPreference) pref).isChecked();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For the user to disable keyguard, we first make them verify their
|
||||
* existing pattern.
|
||||
*/
|
||||
private class LockEnabledPref extends CheckBoxPreference {
|
||||
|
||||
public LockEnabledPref(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClick() {
|
||||
if (isChecked() && mLockPatternUtils.savedPatternExists()) {
|
||||
confirmPatternThenDisable();
|
||||
} else {
|
||||
super.onClick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch screen to confirm the existing lock pattern.
|
||||
* @see #onActivityResult(int, int, android.content.Intent)
|
||||
*/
|
||||
private void confirmPatternThenDisable() {
|
||||
final Intent intent = new Intent();
|
||||
intent.setClassName("com.android.settings", "com.android.settings.ConfirmLockPattern");
|
||||
startActivityForResult(intent, CONFIRM_PATTERN_REQUEST_CODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #confirmPatternThenDisable
|
||||
*/
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode,
|
||||
Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (requestCode != CONFIRM_PATTERN_REQUEST_CODE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
mLockPatternUtils.setLockPatternEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
51
src/com/android/settings/Settings.java
Normal file
51
src/com/android/settings/Settings.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceGroup;
|
||||
import android.provider.Settings.System;
|
||||
|
||||
public class Settings extends PreferenceActivity {
|
||||
|
||||
private static final String KEY_PARENT = "parent";
|
||||
private static final String KEY_CALL_SETTINGS = "call_settings";
|
||||
private static final String KEY_SYNC_SETTINGS = "sync_settings";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.settings);
|
||||
|
||||
PreferenceGroup parent = (PreferenceGroup) findPreference(KEY_PARENT);
|
||||
Utils.updatePreferenceToSpecificActivityOrRemove(this, parent, KEY_SYNC_SETTINGS, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
findPreference(KEY_CALL_SETTINGS).setEnabled(!isAirplaneMode());
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
private boolean isAirplaneMode() {
|
||||
return System.getInt(getContentResolver(),
|
||||
System.AIRPLANE_MODE_ON, 0) > 0;
|
||||
}
|
||||
|
||||
}
|
||||
137
src/com/android/settings/SettingsLicenseActivity.java
Normal file
137
src/com/android/settings/SettingsLicenseActivity.java
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemProperties;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import com.android.internal.app.AlertActivity;
|
||||
import com.android.internal.app.AlertController;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
/**
|
||||
* The "dialog" that shows from "License" in the Settings app.
|
||||
*/
|
||||
public class SettingsLicenseActivity extends AlertActivity {
|
||||
|
||||
private static final String TAG = "SettingsLicenseActivity";
|
||||
private static final boolean LOGV = false || Config.LOGV;
|
||||
|
||||
private static final String DEFAULT_LICENSE_PATH = "/system/etc/NOTICE.html";
|
||||
private static final String PROPERTY_LICENSE_PATH = "ro.config.license_path";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
String fileName = SystemProperties.get(PROPERTY_LICENSE_PATH, DEFAULT_LICENSE_PATH);
|
||||
if (TextUtils.isEmpty(fileName)) {
|
||||
Log.e(TAG, "The system property for the license file is empty.");
|
||||
showErrorAndFinish();
|
||||
return;
|
||||
}
|
||||
|
||||
FileReader fileReader = null;
|
||||
StringBuilder data = null;
|
||||
try {
|
||||
data = new StringBuilder(2048);
|
||||
char tmp[] = new char[2048];
|
||||
int numRead;
|
||||
fileReader = new FileReader(fileName);
|
||||
while ((numRead = fileReader.read(tmp)) >= 0) {
|
||||
data.append(tmp, 0, numRead);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.e(TAG, "License HTML file not found at " + fileName, e);
|
||||
showErrorAndFinish();
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Error reading license HTML file at " + fileName, e);
|
||||
showErrorAndFinish();
|
||||
return;
|
||||
} finally {
|
||||
try {
|
||||
if (fileReader != null) {
|
||||
fileReader.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(data)) {
|
||||
Log.e(TAG, "License HTML is empty (from " + fileName + ")");
|
||||
showErrorAndFinish();
|
||||
return;
|
||||
}
|
||||
|
||||
WebView webView = new WebView(this);
|
||||
|
||||
if (LOGV) Log.v(TAG, "Started encode at " + System.currentTimeMillis());
|
||||
// Need to encode to base64 for WebView to load the contents properly
|
||||
String dataStr;
|
||||
try {
|
||||
byte[] base64Bytes = Base64.encodeBase64(data.toString().getBytes("ISO8859_1"));
|
||||
dataStr = new String(base64Bytes);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Log.e(TAG, "Could not convert to base64", e);
|
||||
showErrorAndFinish();
|
||||
return;
|
||||
}
|
||||
if (LOGV) Log.v(TAG, "Ended encode at " + System.currentTimeMillis());
|
||||
if (LOGV) {
|
||||
Log.v(TAG, "Started test decode at " + System.currentTimeMillis());
|
||||
Base64.decodeBase64(dataStr.getBytes());
|
||||
Log.v(TAG, "Ended decode at " + System.currentTimeMillis());
|
||||
}
|
||||
|
||||
|
||||
// Begin the loading. This will be done in a separate thread in WebView.
|
||||
webView.loadData(dataStr, "text/html", "base64");
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
// Change from 'Loading...' to the real title
|
||||
mAlert.setTitle(getString(R.string.settings_license_activity_title));
|
||||
}
|
||||
});
|
||||
|
||||
final AlertController.AlertParams p = mAlertParams;
|
||||
p.mTitle = getString(R.string.settings_license_activity_loading);
|
||||
p.mView = webView;
|
||||
p.mForceInverseBackground = true;
|
||||
setupAlert();
|
||||
}
|
||||
|
||||
private void showErrorAndFinish() {
|
||||
Toast.makeText(this, R.string.settings_license_activity_unavailable, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
finish();
|
||||
}
|
||||
|
||||
}
|
||||
321
src/com/android/settings/SimLockSettings.java
Normal file
321
src/com/android/settings/SimLockSettings.java
Normal file
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.AsyncResult;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.PreferenceScreen;
|
||||
import com.android.internal.telephony.Phone;
|
||||
import com.android.internal.telephony.PhoneFactory;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* Implements the preference screen to enable/disable SIM lock and
|
||||
* also the dialogs to change the SIM PIN. In the former case, enabling/disabling
|
||||
* the SIM lock will prompt the user for the current PIN.
|
||||
* In the Change PIN case, it prompts the user for old pin, new pin and new pin
|
||||
* again before attempting to change it. Calls the SimCard interface to execute
|
||||
* these operations.
|
||||
*
|
||||
*/
|
||||
public class SimLockSettings extends PreferenceActivity
|
||||
implements EditPinPreference.OnPinEnteredListener {
|
||||
|
||||
private static final int OFF_MODE = 0;
|
||||
// State when enabling/disabling SIM lock
|
||||
private static final int SIM_LOCK_MODE = 1;
|
||||
// State when entering the old pin
|
||||
private static final int SIM_OLD_MODE = 2;
|
||||
// State when entering the new pin - first time
|
||||
private static final int SIM_NEW_MODE = 3;
|
||||
// State when entering the new pin - second time
|
||||
private static final int SIM_REENTER_MODE = 4;
|
||||
|
||||
// Keys in xml file
|
||||
private static final String PIN_DIALOG = "sim_pin";
|
||||
private static final String PIN_TOGGLE = "sim_toggle";
|
||||
// Keys in icicle
|
||||
private static final String DIALOG_STATE = "dialogState";
|
||||
private static final String DIALOG_PIN = "dialogPin";
|
||||
private static final String DIALOG_ERROR = "dialogError";
|
||||
private static final String ENABLE_TO_STATE = "enableState";
|
||||
|
||||
private static final int MIN_PIN_LENGTH = 4;
|
||||
private static final int MAX_PIN_LENGTH = 8;
|
||||
// Which dialog to show next when popped up
|
||||
private int mDialogState = OFF_MODE;
|
||||
|
||||
private String mPin;
|
||||
private String mOldPin;
|
||||
private String mNewPin;
|
||||
private String mError;
|
||||
// Are we trying to enable or disable SIM lock?
|
||||
private boolean mToState;
|
||||
|
||||
private Phone mPhone;
|
||||
|
||||
private EditPinPreference mPinDialog;
|
||||
private CheckBoxPreference mPinToggle;
|
||||
|
||||
private Resources mRes;
|
||||
|
||||
// For async handler to identify request type
|
||||
private static final int ENABLE_SIM_PIN_COMPLETE = 100;
|
||||
private static final int CHANGE_SIM_PIN_COMPLETE = 101;
|
||||
|
||||
// For replies from SimCard interface
|
||||
private Handler mHandler = new Handler() {
|
||||
public void handleMessage(Message msg) {
|
||||
AsyncResult ar = (AsyncResult) msg.obj;
|
||||
switch (msg.what) {
|
||||
case ENABLE_SIM_PIN_COMPLETE:
|
||||
simLockChanged(ar.exception == null);
|
||||
break;
|
||||
case CHANGE_SIM_PIN_COMPLETE:
|
||||
simPinChanged(ar.exception == null);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// For top-level settings screen to query
|
||||
static boolean isSimLockEnabled() {
|
||||
return PhoneFactory.getDefaultPhone().getSimCard().getSimLockEnabled();
|
||||
}
|
||||
|
||||
static String getSummary(Context context) {
|
||||
Resources res = context.getResources();
|
||||
String summary = isSimLockEnabled()
|
||||
? res.getString(R.string.sim_lock_on)
|
||||
: res.getString(R.string.sim_lock_off);
|
||||
return summary;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.sim_lock_settings);
|
||||
|
||||
mPinDialog = (EditPinPreference) findPreference(PIN_DIALOG);
|
||||
mPinToggle = (CheckBoxPreference) findPreference(PIN_TOGGLE);
|
||||
if (savedInstanceState != null && savedInstanceState.containsKey(DIALOG_STATE)) {
|
||||
mDialogState = savedInstanceState.getInt(DIALOG_STATE);
|
||||
mPin = savedInstanceState.getString(DIALOG_PIN);
|
||||
mError = savedInstanceState.getString(DIALOG_ERROR);
|
||||
mToState = savedInstanceState.getBoolean(ENABLE_TO_STATE);
|
||||
}
|
||||
|
||||
mPinDialog.setOnPinEnteredListener(this);
|
||||
|
||||
// Don't need any changes to be remembered
|
||||
getPreferenceScreen().setPersistent(false);
|
||||
|
||||
mPhone = PhoneFactory.getDefaultPhone();
|
||||
mRes = getResources();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
mPinToggle.setChecked(mPhone.getSimCard().getSimLockEnabled());
|
||||
|
||||
if (mDialogState != OFF_MODE) {
|
||||
showPinDialog();
|
||||
} else {
|
||||
// Prep for standard click on "Change PIN"
|
||||
resetDialogState();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle out) {
|
||||
// Need to store this state for slider open/close
|
||||
// There is one case where the dialog is popped up by the preference
|
||||
// framework. In that case, let the preference framework store the
|
||||
// dialog state. In other cases, where this activity manually launches
|
||||
// the dialog, store the state of the dialog.
|
||||
if (mPinDialog.isDialogOpen()) {
|
||||
out.putInt(DIALOG_STATE, mDialogState);
|
||||
out.putString(DIALOG_PIN, mPinDialog.getEditText().getText().toString());
|
||||
out.putString(DIALOG_ERROR, mError);
|
||||
out.putBoolean(ENABLE_TO_STATE, mToState);
|
||||
} else {
|
||||
super.onSaveInstanceState(out);
|
||||
}
|
||||
}
|
||||
|
||||
private void showPinDialog() {
|
||||
if (mDialogState == OFF_MODE) {
|
||||
return;
|
||||
}
|
||||
setDialogValues();
|
||||
|
||||
mPinDialog.showPinDialog();
|
||||
}
|
||||
|
||||
private void setDialogValues() {
|
||||
mPinDialog.setText(mPin);
|
||||
String message = "";
|
||||
switch (mDialogState) {
|
||||
case SIM_LOCK_MODE:
|
||||
message = mRes.getString(R.string.sim_enter_pin);
|
||||
mPinDialog.setDialogTitle(mToState
|
||||
? mRes.getString(R.string.sim_enable_sim_lock)
|
||||
: mRes.getString(R.string.sim_disable_sim_lock));
|
||||
break;
|
||||
case SIM_OLD_MODE:
|
||||
message = mRes.getString(R.string.sim_enter_old);
|
||||
mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
|
||||
break;
|
||||
case SIM_NEW_MODE:
|
||||
message = mRes.getString(R.string.sim_enter_new);
|
||||
mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
|
||||
break;
|
||||
case SIM_REENTER_MODE:
|
||||
message = mRes.getString(R.string.sim_reenter_new);
|
||||
mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
|
||||
break;
|
||||
}
|
||||
if (mError != null) {
|
||||
message = mError + "\n" + message;
|
||||
mError = null;
|
||||
}
|
||||
mPinDialog.setDialogMessage(message);
|
||||
}
|
||||
|
||||
public void onPinEntered(EditPinPreference preference, boolean positiveResult) {
|
||||
if (!positiveResult) {
|
||||
resetDialogState();
|
||||
return;
|
||||
}
|
||||
|
||||
mPin = preference.getText();
|
||||
if (!reasonablePin(mPin)) {
|
||||
// inject error message and display dialog again
|
||||
mError = mRes.getString(R.string.sim_bad_pin);
|
||||
showPinDialog();
|
||||
return;
|
||||
}
|
||||
switch (mDialogState) {
|
||||
case SIM_LOCK_MODE:
|
||||
tryChangeSimLockState();
|
||||
break;
|
||||
case SIM_OLD_MODE:
|
||||
mOldPin = mPin;
|
||||
mDialogState = SIM_NEW_MODE;
|
||||
mError = null;
|
||||
mPin = null;
|
||||
showPinDialog();
|
||||
break;
|
||||
case SIM_NEW_MODE:
|
||||
mNewPin = mPin;
|
||||
mDialogState = SIM_REENTER_MODE;
|
||||
mPin = null;
|
||||
showPinDialog();
|
||||
break;
|
||||
case SIM_REENTER_MODE:
|
||||
if (!mPin.equals(mNewPin)) {
|
||||
mError = mRes.getString(R.string.sim_pins_dont_match);
|
||||
mDialogState = SIM_NEW_MODE;
|
||||
mPin = null;
|
||||
showPinDialog();
|
||||
} else {
|
||||
mError = null;
|
||||
tryChangePin();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
|
||||
if (preference == mPinToggle) {
|
||||
// Get the new, preferred state
|
||||
mToState = mPinToggle.isChecked();
|
||||
// Flip it back and pop up pin dialog
|
||||
mPinToggle.setChecked(!mToState);
|
||||
mDialogState = SIM_LOCK_MODE;
|
||||
showPinDialog();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void tryChangeSimLockState() {
|
||||
// Try to change sim lock. If it succeeds, toggle the lock state and
|
||||
// reset dialog state. Else inject error message and show dialog again.
|
||||
Message callback = Message.obtain(mHandler, ENABLE_SIM_PIN_COMPLETE);
|
||||
mPhone.getSimCard().setSimLockEnabled(mToState, mPin, callback);
|
||||
|
||||
}
|
||||
|
||||
private void simLockChanged(boolean success) {
|
||||
if (success) {
|
||||
mPinToggle.setChecked(mToState);
|
||||
} else {
|
||||
// TODO: I18N
|
||||
Toast.makeText(this, mRes.getString(R.string.sim_lock_failed), Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
resetDialogState();
|
||||
}
|
||||
|
||||
private void simPinChanged(boolean success) {
|
||||
if (!success) {
|
||||
// TODO: I18N
|
||||
Toast.makeText(this, mRes.getString(R.string.sim_change_failed),
|
||||
Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
} else {
|
||||
Toast.makeText(this, mRes.getString(R.string.sim_change_succeeded),
|
||||
Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
|
||||
}
|
||||
resetDialogState();
|
||||
}
|
||||
|
||||
private void tryChangePin() {
|
||||
Message callback = Message.obtain(mHandler, CHANGE_SIM_PIN_COMPLETE);
|
||||
mPhone.getSimCard().changeSimLockPassword(mOldPin,
|
||||
mNewPin, callback);
|
||||
}
|
||||
|
||||
private boolean reasonablePin(String pin) {
|
||||
if (pin == null || pin.length() < MIN_PIN_LENGTH || pin.length() > MAX_PIN_LENGTH) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void resetDialogState() {
|
||||
mError = null;
|
||||
mDialogState = SIM_OLD_MODE; // Default for when Change PIN is clicked
|
||||
mPin = "";
|
||||
setDialogValues();
|
||||
}
|
||||
}
|
||||
172
src/com/android/settings/SoundAndDisplaySettings.java
Normal file
172
src/com/android/settings/SoundAndDisplaySettings.java
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Bundle;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
|
||||
public class SoundAndDisplaySettings extends PreferenceActivity implements
|
||||
Preference.OnPreferenceChangeListener {
|
||||
private static final String TAG = "SoundAndDisplaysSettings";
|
||||
|
||||
/** If there is no setting in the provider, use this. */
|
||||
private static final int FALLBACK_SCREEN_TIMEOUT_VALUE = 30000;
|
||||
|
||||
private static final String KEY_SILENT = "silent";
|
||||
private static final String KEY_VIBRATE = "vibrate";
|
||||
private static final String KEY_SCREEN_TIMEOUT = "screen_timeout";
|
||||
private static final String KEY_DTMF_TONE = "dtmf_tone";
|
||||
private static final String KEY_SOUND_EFFECTS = "sound_effects";
|
||||
|
||||
private CheckBoxPreference mSilent;
|
||||
private CheckBoxPreference mVibrate;
|
||||
private CheckBoxPreference mDtmfTone;
|
||||
private CheckBoxPreference mSoundEffects;
|
||||
|
||||
private AudioManager mAudioManager;
|
||||
|
||||
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
||||
int ringerMode = intent
|
||||
.getIntExtra(AudioManager.EXTRA_RINGER_MODE, AudioManager.RINGER_MODE_NORMAL);
|
||||
boolean isSilentMode = ringerMode != AudioManager.RINGER_MODE_NORMAL;
|
||||
|
||||
if (mSilent.isChecked() != isSilentMode) {
|
||||
mSilent.setChecked(isSilentMode);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
ContentResolver resolver = getContentResolver();
|
||||
|
||||
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
|
||||
|
||||
addPreferencesFromResource(R.xml.sound_and_display_settings);
|
||||
|
||||
mSilent = (CheckBoxPreference) findPreference(KEY_SILENT);
|
||||
mVibrate = (CheckBoxPreference) findPreference(KEY_VIBRATE);
|
||||
mDtmfTone = (CheckBoxPreference) findPreference(KEY_DTMF_TONE);
|
||||
mDtmfTone.setPersistent(false);
|
||||
mDtmfTone.setChecked(Settings.System.getInt(resolver,
|
||||
Settings.System.DTMF_TONE_WHEN_DIALING, 1) != 0);
|
||||
mSoundEffects = (CheckBoxPreference) findPreference(KEY_SOUND_EFFECTS);
|
||||
mSoundEffects.setPersistent(false);
|
||||
mSoundEffects.setChecked(Settings.System.getInt(resolver,
|
||||
Settings.System.SOUND_EFFECTS_ENABLED, 0) != 0);
|
||||
|
||||
ListPreference screenTimeoutPreference =
|
||||
(ListPreference) findPreference(KEY_SCREEN_TIMEOUT);
|
||||
screenTimeoutPreference.setValue(String.valueOf(Settings.System.getInt(
|
||||
getContentResolver(), SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE)));
|
||||
screenTimeoutPreference.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
updateState(true);
|
||||
|
||||
IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
|
||||
registerReceiver(mReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
unregisterReceiver(mReceiver);
|
||||
}
|
||||
|
||||
private void updateState(boolean force) {
|
||||
final boolean silent = mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL;
|
||||
final boolean phoneVibrate = mAudioManager
|
||||
.getVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER)
|
||||
== AudioManager.VIBRATE_SETTING_ON;
|
||||
|
||||
if (silent != mSilent.isChecked() || force) {
|
||||
mSilent.setChecked(silent);
|
||||
}
|
||||
|
||||
if (phoneVibrate != mVibrate.isChecked() || force) {
|
||||
mVibrate.setChecked(phoneVibrate);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
|
||||
|
||||
if (preference == mSilent) {
|
||||
final boolean silent = mSilent.isChecked();
|
||||
mAudioManager.setRingerMode(silent ? AudioManager.RINGER_MODE_SILENT
|
||||
: AudioManager.RINGER_MODE_NORMAL);
|
||||
|
||||
} else if (preference == mVibrate) {
|
||||
final boolean vibrate = mVibrate.isChecked();
|
||||
mAudioManager.setVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER,
|
||||
vibrate ? AudioManager.VIBRATE_SETTING_ON
|
||||
: AudioManager.VIBRATE_SETTING_OFF);
|
||||
} else if (preference == mDtmfTone) {
|
||||
Settings.System.putInt(getContentResolver(), Settings.System.DTMF_TONE_WHEN_DIALING,
|
||||
mDtmfTone.isChecked() ? 1 : 0);
|
||||
|
||||
} else if (preference == mSoundEffects) {
|
||||
if (mSoundEffects.isChecked()) {
|
||||
mAudioManager.loadSoundEffects();
|
||||
} else {
|
||||
mAudioManager.unloadSoundEffects();
|
||||
}
|
||||
Settings.System.putInt(getContentResolver(), Settings.System.SOUND_EFFECTS_ENABLED,
|
||||
mSoundEffects.isChecked() ? 1 : 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onPreferenceChange(Preference preference, Object objValue) {
|
||||
if (KEY_SCREEN_TIMEOUT.equals(preference.getKey())) {
|
||||
int value = Integer.parseInt((String) objValue);
|
||||
try {
|
||||
Settings.System.putInt(getContentResolver(),
|
||||
SCREEN_OFF_TIMEOUT, value);
|
||||
} catch (NumberFormatException e) {
|
||||
Log.e(TAG, "could not persist screen timeout setting", e);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
31
src/com/android/settings/TestingSettings.java
Normal file
31
src/com/android/settings/TestingSettings.java
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceActivity;
|
||||
|
||||
public class TestingSettings extends PreferenceActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.testing_settings);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.android.settings;
|
||||
|
||||
import android.provider.Telephony;
|
||||
import static android.provider.Telephony.Intents.SECRET_CODE_ACTION;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
|
||||
public class TestingSettingsBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
public TestingSettingsBroadcastReceiver() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent.getAction().equals(SECRET_CODE_ACTION)) {
|
||||
Intent i = new Intent(Intent.ACTION_MAIN);
|
||||
i.setClass(context, TestingSettings.class);
|
||||
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
91
src/com/android/settings/Utils.java
Normal file
91
src/com/android/settings/Utils.java
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Copyright (C) 2007 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceGroup;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Utils {
|
||||
|
||||
/**
|
||||
* Set the preference's title to the matching activity's label.
|
||||
*/
|
||||
public static final int UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY = 1;
|
||||
|
||||
/**
|
||||
* Finds a matching activity for a preference's intent. If a matching
|
||||
* activity is not found, it will remove the preference.
|
||||
*
|
||||
* @param context The context.
|
||||
* @param parentPreferenceGroup The preference group that contains the
|
||||
* preference whose intent is being resolved.
|
||||
* @param preferenceKey The key of the preference whose intent is being
|
||||
* resolved.
|
||||
* @param flags 0 or one or more of
|
||||
* {@link #UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY}
|
||||
* .
|
||||
* @return Whether an activity was found. If false, the preference was
|
||||
* removed.
|
||||
*/
|
||||
public static boolean updatePreferenceToSpecificActivityOrRemove(Context context,
|
||||
PreferenceGroup parentPreferenceGroup, String preferenceKey, int flags) {
|
||||
|
||||
Preference preference = parentPreferenceGroup.findPreference(preferenceKey);
|
||||
if (preference == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Intent intent = preference.getIntent();
|
||||
if (intent != null) {
|
||||
// Find the activity that is in the system image
|
||||
PackageManager pm = context.getPackageManager();
|
||||
List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
|
||||
int listSize = list.size();
|
||||
for (int i = 0; i < listSize; i++) {
|
||||
ResolveInfo resolveInfo = list.get(i);
|
||||
if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
|
||||
!= 0) {
|
||||
|
||||
// Replace the intent with this specific activity
|
||||
preference.setIntent(new Intent().setClassName(
|
||||
resolveInfo.activityInfo.packageName,
|
||||
resolveInfo.activityInfo.name));
|
||||
|
||||
if ((flags & UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY) != 0) {
|
||||
// Set the preference title to the activity's label
|
||||
preference.setTitle(resolveInfo.loadLabel(pm));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Did not find a matching activity, so remove the preference
|
||||
parentPreferenceGroup.removePreference(preference);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
210
src/com/android/settings/WirelessSettings.java
Normal file
210
src/com/android/settings/WirelessSettings.java
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import com.android.settings.wifi.WifiEnabler;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothIntent;
|
||||
import android.bluetooth.IBluetoothDeviceCallback;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.provider.Settings;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class WirelessSettings extends PreferenceActivity {
|
||||
|
||||
private static final String KEY_TOGGLE_AIRPLANE = "toggle_airplane";
|
||||
private static final String KEY_TOGGLE_BLUETOOTH = "toggle_bluetooth";
|
||||
private static final String KEY_TOGGLE_WIFI = "toggle_wifi";
|
||||
|
||||
private WifiEnabler mWifiEnabler;
|
||||
private AirplaneModeEnabler mAirplaneModeEnabler;
|
||||
|
||||
private CheckBoxPreference mToggleBluetooth;
|
||||
|
||||
private IntentFilter mIntentFilter;
|
||||
|
||||
private static final int EVENT_FAILED_BT_ENABLE = 1;
|
||||
private static final int EVENT_PASSED_BT_ENABLE = 2;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.wireless_settings);
|
||||
|
||||
mIntentFilter = new IntentFilter();
|
||||
mIntentFilter.addAction(BluetoothIntent.ENABLED_ACTION);
|
||||
mIntentFilter.addAction(BluetoothIntent.DISABLED_ACTION);
|
||||
|
||||
initToggles();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
refreshToggles();
|
||||
registerReceiver(mReceiver, mIntentFilter);
|
||||
|
||||
mWifiEnabler.resume();
|
||||
mAirplaneModeEnabler.resume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
unregisterReceiver(mReceiver);
|
||||
|
||||
mWifiEnabler.pause();
|
||||
mAirplaneModeEnabler.pause();
|
||||
}
|
||||
|
||||
private void initToggles() {
|
||||
|
||||
mWifiEnabler = new WifiEnabler(
|
||||
this,
|
||||
(WifiManager) getSystemService(WIFI_SERVICE),
|
||||
(CheckBoxPreference) findPreference(KEY_TOGGLE_WIFI));
|
||||
|
||||
mAirplaneModeEnabler = new AirplaneModeEnabler(
|
||||
this,
|
||||
(CheckBoxPreference) findPreference(KEY_TOGGLE_AIRPLANE));
|
||||
|
||||
mToggleBluetooth = (CheckBoxPreference) findPreference(KEY_TOGGLE_BLUETOOTH);
|
||||
mToggleBluetooth.setPersistent(false);
|
||||
}
|
||||
|
||||
private void refreshToggles() {
|
||||
mToggleBluetooth.setChecked(isBluetoothEnabled());
|
||||
mToggleBluetooth.setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
|
||||
if (preference == mToggleBluetooth) {
|
||||
setBluetoothEnabled(mToggleBluetooth.isChecked());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isBluetoothEnabled() {
|
||||
BluetoothDevice device = (BluetoothDevice)getSystemService(BLUETOOTH_SERVICE);
|
||||
if (device != null) {
|
||||
return device.isEnabled();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void setBluetoothEnabled(boolean enabled) {
|
||||
try {
|
||||
BluetoothDevice device = (BluetoothDevice)getSystemService(BLUETOOTH_SERVICE);
|
||||
if (enabled) {
|
||||
// Turn it off until intent or callback is delivered
|
||||
mToggleBluetooth.setChecked(false);
|
||||
if (device.enable(mBtCallback)) {
|
||||
mToggleBluetooth.setSummary(R.string.bluetooth_enabling);
|
||||
mToggleBluetooth.setEnabled(false);
|
||||
}
|
||||
} else {
|
||||
if (device.disable()) {
|
||||
Settings.System.putInt(getContentResolver(),
|
||||
Settings.System.BLUETOOTH_ON, 0);
|
||||
} else {
|
||||
// Unusual situation, that you can't turn off bluetooth
|
||||
mToggleBluetooth.setChecked(true);
|
||||
}
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
// TODO: 1071858
|
||||
mToggleBluetooth.setChecked(false);
|
||||
mToggleBluetooth.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
private IBluetoothDeviceCallback mBtCallback = new IBluetoothDeviceCallback.Stub() {
|
||||
|
||||
public void onEnableResult(int res) {
|
||||
switch (res) {
|
||||
case BluetoothDevice.RESULT_FAILURE:
|
||||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_FAILED_BT_ENABLE, 0));
|
||||
break;
|
||||
case BluetoothDevice.RESULT_SUCCESS:
|
||||
mHandler.sendMessage(mHandler.obtainMessage(EVENT_PASSED_BT_ENABLE, 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void onCreateBondingResult(String device, int res) {
|
||||
// Don't care
|
||||
}
|
||||
public void onGetRemoteServiceChannelResult(String address, int channel) { }
|
||||
};
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action.equals(BluetoothIntent.ENABLED_ACTION)) {
|
||||
updateBtStatus(true);
|
||||
} else if (action.equals(BluetoothIntent.DISABLED_ACTION)) {
|
||||
mToggleBluetooth.setChecked(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void updateBtStatus(boolean enabled) {
|
||||
mToggleBluetooth.setChecked(enabled);
|
||||
mToggleBluetooth.setEnabled(true);
|
||||
mToggleBluetooth.setSummary(R.string.bluetooth_quick_toggle_summary);
|
||||
if (enabled) {
|
||||
Settings.System.putInt(getContentResolver(),
|
||||
Settings.System.BLUETOOTH_ON, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private Handler mHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case EVENT_PASSED_BT_ENABLE:
|
||||
updateBtStatus(true);
|
||||
break;
|
||||
case EVENT_FAILED_BT_ENABLE:
|
||||
updateBtStatus(false);
|
||||
Toast.makeText(WirelessSettings.this,
|
||||
getResources().getString(R.string.bluetooth_failed_to_enable),
|
||||
Toast.LENGTH_SHORT).show();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
273
src/com/android/settings/ZoneList.java
Normal file
273
src/com/android/settings/ZoneList.java
Normal file
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.ListActivity;
|
||||
import android.content.Context;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SimpleAdapter;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* This activity displays a list of time zones that match a filter string
|
||||
* such as "Africa", "Europe", etc. Choosing an item from the list will set
|
||||
* the time zone. Pressing Back without choosing from the list will not
|
||||
* result in a change in the time zone setting.
|
||||
*/
|
||||
public class ZoneList extends ListActivity {
|
||||
|
||||
private static final String TAG = "ZoneList";
|
||||
private static final String KEY_ID = "id";
|
||||
private static final String KEY_DISPLAYNAME = "name";
|
||||
private static final String KEY_GMT = "gmt";
|
||||
private static final String KEY_OFFSET = "offset";
|
||||
private static final String XMLTAG_TIMEZONE = "timezone";
|
||||
|
||||
private static final int HOURS_1 = 60 * 60000;
|
||||
private static final int HOURS_24 = 24 * HOURS_1;
|
||||
private static final int HOURS_HALF = HOURS_1 / 2;
|
||||
|
||||
private static final int MENU_TIMEZONE = Menu.FIRST+1;
|
||||
private static final int MENU_ALPHABETICAL = Menu.FIRST;
|
||||
|
||||
// Initial focus position
|
||||
private int mDefault;
|
||||
|
||||
private boolean mSortedByTimezone;
|
||||
|
||||
private SimpleAdapter mTimezoneSortedAdapter;
|
||||
private SimpleAdapter mAlphabeticalAdapter;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
String[] from = new String[] {KEY_DISPLAYNAME, KEY_GMT};
|
||||
int[] to = new int[] {android.R.id.text1, android.R.id.text2};
|
||||
|
||||
MyComparator comparator = new MyComparator(KEY_OFFSET);
|
||||
|
||||
List<HashMap> timezoneSortedList = getZones();
|
||||
Collections.sort(timezoneSortedList, comparator);
|
||||
mTimezoneSortedAdapter = new SimpleAdapter(this,
|
||||
(List) timezoneSortedList,
|
||||
android.R.layout.simple_list_item_2,
|
||||
from,
|
||||
to);
|
||||
|
||||
List<HashMap> alphabeticalList = new ArrayList<HashMap>(timezoneSortedList);
|
||||
comparator.setSortingKey(KEY_DISPLAYNAME);
|
||||
Collections.sort(alphabeticalList, comparator);
|
||||
mAlphabeticalAdapter = new SimpleAdapter(this,
|
||||
(List) alphabeticalList,
|
||||
android.R.layout.simple_list_item_2,
|
||||
from,
|
||||
to);
|
||||
|
||||
// Sets the adapter
|
||||
setSorting(true);
|
||||
|
||||
// If current timezone is in this list, move focus to it
|
||||
setSelection(mDefault);
|
||||
|
||||
// Assume user may press Back
|
||||
setResult(RESULT_CANCELED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
menu.add(0, MENU_ALPHABETICAL, 0, R.string.zone_list_menu_sort_alphabetically)
|
||||
.setIcon(R.drawable.ic_menu_sort_alphabetically);
|
||||
menu.add(0, MENU_TIMEZONE, 0, R.string.zone_list_menu_sort_by_timezone)
|
||||
.setIcon(R.drawable.ic_menu_3d_globe);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
|
||||
if (mSortedByTimezone) {
|
||||
menu.findItem(MENU_TIMEZONE).setVisible(false);
|
||||
menu.findItem(MENU_ALPHABETICAL).setVisible(true);
|
||||
} else {
|
||||
menu.findItem(MENU_TIMEZONE).setVisible(true);
|
||||
menu.findItem(MENU_ALPHABETICAL).setVisible(false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
|
||||
case MENU_TIMEZONE:
|
||||
setSorting(true);
|
||||
return true;
|
||||
|
||||
case MENU_ALPHABETICAL:
|
||||
setSorting(false);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void setSorting(boolean timezone) {
|
||||
setListAdapter(timezone ? mTimezoneSortedAdapter : mAlphabeticalAdapter);
|
||||
mSortedByTimezone = timezone;
|
||||
}
|
||||
|
||||
private List<HashMap> getZones() {
|
||||
List<HashMap> myData = new ArrayList<HashMap>();
|
||||
long date = Calendar.getInstance().getTimeInMillis();
|
||||
try {
|
||||
XmlResourceParser xrp = getResources().getXml(R.xml.timezones);
|
||||
while (xrp.next() != XmlResourceParser.START_TAG)
|
||||
;
|
||||
xrp.next();
|
||||
while (xrp.getEventType() != XmlResourceParser.END_TAG) {
|
||||
while (xrp.getEventType() != XmlResourceParser.START_TAG) {
|
||||
if (xrp.getEventType() == XmlResourceParser.END_DOCUMENT) {
|
||||
return myData;
|
||||
}
|
||||
xrp.next();
|
||||
}
|
||||
if (xrp.getName().equals(XMLTAG_TIMEZONE)) {
|
||||
String id = xrp.getAttributeValue(0);
|
||||
String displayName = xrp.nextText();
|
||||
addItem(myData, id, displayName, date);
|
||||
}
|
||||
while (xrp.getEventType() != XmlResourceParser.END_TAG) {
|
||||
xrp.next();
|
||||
}
|
||||
xrp.next();
|
||||
}
|
||||
xrp.close();
|
||||
} catch (XmlPullParserException xppe) {
|
||||
Log.e(TAG, "Ill-formatted timezones.xml file");
|
||||
} catch (java.io.IOException ioe) {
|
||||
Log.e(TAG, "Unable to read timezones.xml file");
|
||||
}
|
||||
|
||||
return myData;
|
||||
}
|
||||
|
||||
protected void addItem(List<HashMap> myData, String id, String displayName,
|
||||
long date) {
|
||||
HashMap map = new HashMap();
|
||||
map.put(KEY_ID, id);
|
||||
map.put(KEY_DISPLAYNAME, displayName);
|
||||
TimeZone tz = TimeZone.getTimeZone(id);
|
||||
int offset = tz.getOffset(date);
|
||||
int p = Math.abs(offset);
|
||||
StringBuilder name = new StringBuilder();
|
||||
name.append("GMT");
|
||||
|
||||
if (offset < 0) {
|
||||
name.append('-');
|
||||
} else {
|
||||
name.append('+');
|
||||
}
|
||||
|
||||
name.append(p / (HOURS_1));
|
||||
name.append(':');
|
||||
|
||||
int min = p / 60000;
|
||||
min %= 60;
|
||||
|
||||
if (min < 10) {
|
||||
name.append('0');
|
||||
}
|
||||
name.append(min);
|
||||
|
||||
map.put(KEY_GMT, name.toString());
|
||||
map.put(KEY_OFFSET, offset);
|
||||
|
||||
if (id.equals(TimeZone.getDefault().getID())) {
|
||||
mDefault = myData.size();
|
||||
}
|
||||
|
||||
myData.add(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
Map map = (Map) l.getItemAtPosition(position);
|
||||
// Update the system timezone value
|
||||
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
||||
alarm.setTimeZone((String) map.get(KEY_ID));
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
}
|
||||
|
||||
private static class MyComparator implements Comparator<HashMap> {
|
||||
private String mSortingKey;
|
||||
|
||||
public MyComparator(String sortingKey) {
|
||||
mSortingKey = sortingKey;
|
||||
}
|
||||
|
||||
public void setSortingKey(String sortingKey) {
|
||||
mSortingKey = sortingKey;
|
||||
}
|
||||
|
||||
public int compare(HashMap map1, HashMap map2) {
|
||||
Object value1 = map1.get(mSortingKey);
|
||||
Object value2 = map2.get(mSortingKey);
|
||||
|
||||
/*
|
||||
* This should never happen, but just in-case, put non-comparable
|
||||
* items at the end.
|
||||
*/
|
||||
if (!isComparable(value1)) {
|
||||
return isComparable(value2) ? 1 : 0;
|
||||
} else if (!isComparable(value2)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ((Comparable) value1).compareTo(value2);
|
||||
}
|
||||
|
||||
private boolean isComparable(Object value) {
|
||||
return (value != null) && (value instanceof Comparable);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
70
src/com/android/settings/ZonePicker.java
Normal file
70
src/com/android/settings/ZonePicker.java
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2006 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.ListActivity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ZonePicker extends ListActivity {
|
||||
|
||||
private ArrayAdapter<CharSequence> mFilterAdapter;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
mFilterAdapter = ArrayAdapter.createFromResource(this,
|
||||
R.array.timezone_filters, android.R.layout.simple_list_item_1);
|
||||
setListAdapter(mFilterAdapter);
|
||||
}
|
||||
|
||||
protected void addItem(List<Map> data, String name, String zone) {
|
||||
HashMap temp = new HashMap();
|
||||
temp.put("title", name);
|
||||
temp.put("zone", zone);
|
||||
data.add(temp);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
String filter = (String) mFilterAdapter.getItem(position);
|
||||
// If All is chosen, reset the filter
|
||||
if (filter.equals("All")) {
|
||||
filter = null;
|
||||
}
|
||||
Intent zoneList = new Intent();
|
||||
zoneList.setClass(this, ZoneList.class);
|
||||
zoneList.putExtra("filter", filter);
|
||||
|
||||
startActivityForResult(zoneList, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
// If subactivity has resulted in a timezone selection, close this act.
|
||||
if (resultCode == RESULT_OK) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
178
src/com/android/settings/deviceinfo/Memory.java
Normal file
178
src/com/android/settings/deviceinfo/Memory.java
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.deviceinfo;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.Environment;
|
||||
import android.os.IMountService;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.StatFs;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
public class Memory extends PreferenceActivity {
|
||||
|
||||
private static final String MEMORY_SD_SIZE = "memory_sd_size";
|
||||
|
||||
private static final String MEMORY_SD_AVAIL = "memory_sd_avail";
|
||||
|
||||
private static final String MEMORY_SD_UNMOUNT = "memory_sd_unmount";
|
||||
|
||||
private Resources mRes;
|
||||
|
||||
private Preference mSdSize;
|
||||
private Preference mSdAvail;
|
||||
private Preference mSdUnmount;
|
||||
|
||||
private IMountService mMountService;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
addPreferencesFromResource(R.xml.device_info_memory);
|
||||
|
||||
mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
|
||||
|
||||
mRes = getResources();
|
||||
mSdSize = findPreference(MEMORY_SD_SIZE);
|
||||
mSdAvail = findPreference(MEMORY_SD_AVAIL);
|
||||
mSdUnmount = findPreference(MEMORY_SD_UNMOUNT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_REMOVED);
|
||||
intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
|
||||
intentFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
|
||||
intentFilter.addAction(Intent.ACTION_MEDIA_SHARED);
|
||||
intentFilter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
|
||||
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
|
||||
intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
|
||||
intentFilter.addDataScheme("file");
|
||||
registerReceiver(mReceiver, intentFilter);
|
||||
|
||||
updateMemoryStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
unregisterReceiver(mReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
|
||||
if (preference == mSdUnmount) {
|
||||
unmount();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
updateMemoryStatus();
|
||||
}
|
||||
};
|
||||
|
||||
private void unmount() {
|
||||
try {
|
||||
mMountService.unmountMedia(Environment.getExternalStorageDirectory().toString());
|
||||
} catch (RemoteException ex) {
|
||||
// Failed for some reason, try to update UI to actual state
|
||||
updateMemoryStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateMemoryStatus() {
|
||||
String status = Environment.getExternalStorageState();
|
||||
String readOnly = "";
|
||||
if (status.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
|
||||
status = Environment.MEDIA_MOUNTED;
|
||||
readOnly = mRes.getString(R.string.read_only);
|
||||
}
|
||||
|
||||
if (status.equals(Environment.MEDIA_MOUNTED)) {
|
||||
try {
|
||||
File path = Environment.getExternalStorageDirectory();
|
||||
StatFs stat = new StatFs(path.getPath());
|
||||
long blockSize = stat.getBlockSize();
|
||||
long totalBlocks = stat.getBlockCount();
|
||||
long availableBlocks = stat.getAvailableBlocks();
|
||||
|
||||
mSdSize.setSummary(formatSize(totalBlocks * blockSize));
|
||||
mSdAvail.setSummary(formatSize(availableBlocks * blockSize) + readOnly);
|
||||
mSdUnmount.setEnabled(true);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// this can occur if the SD card is removed, but we haven't received the
|
||||
// ACTION_MEDIA_REMOVED Intent yet.
|
||||
status = Environment.MEDIA_REMOVED;
|
||||
}
|
||||
|
||||
} else {
|
||||
mSdSize.setSummary(mRes.getString(R.string.sd_unavailable));
|
||||
mSdAvail.setSummary(mRes.getString(R.string.sd_unavailable));
|
||||
mSdUnmount.setEnabled(false);
|
||||
}
|
||||
|
||||
File path = Environment.getDataDirectory();
|
||||
StatFs stat = new StatFs(path.getPath());
|
||||
long blockSize = stat.getBlockSize();
|
||||
long availableBlocks = stat.getAvailableBlocks();
|
||||
findPreference("memory_internal_avail").setSummary(formatSize(availableBlocks * blockSize));
|
||||
}
|
||||
|
||||
private String formatSize(long size) {
|
||||
String suffix = null;
|
||||
|
||||
// add KB or MB suffix if size is greater than 1K or 1M
|
||||
if (size >= 1024) {
|
||||
suffix = " KB";
|
||||
size /= 1024;
|
||||
if (size >= 1024) {
|
||||
suffix = " MB";
|
||||
size /= 1024;
|
||||
}
|
||||
}
|
||||
|
||||
DecimalFormat formatter = new DecimalFormat();
|
||||
formatter.setGroupingSize(3);
|
||||
String result = formatter.format(size);
|
||||
|
||||
if (suffix != null)
|
||||
result = result + suffix;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
378
src/com/android/settings/deviceinfo/Status.java
Normal file
378
src/com/android/settings/deviceinfo/Status.java
Normal file
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.deviceinfo;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Resources;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.internal.telephony.Phone;
|
||||
import com.android.internal.telephony.PhoneFactory;
|
||||
import com.android.internal.telephony.PhoneStateIntentReceiver;
|
||||
import com.android.internal.telephony.TelephonyProperties;
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* Display the following information
|
||||
* # Phone Number
|
||||
* # Network
|
||||
* # Roaming
|
||||
* # IMEI
|
||||
* # IMSI
|
||||
* # Network type
|
||||
* # Signal Strength
|
||||
* # Battery Strength : TODO
|
||||
* # Uptime
|
||||
* # Awake Time
|
||||
* # XMPP/buzz/tickle status : TODO
|
||||
*
|
||||
*/
|
||||
public class Status extends PreferenceActivity {
|
||||
|
||||
private static final String KEY_WIFI_MAC_ADDRESS = "wifi_mac_address";
|
||||
private static final String KEY_BT_ADDRESS = "bt_address";
|
||||
private static final int EVENT_SIGNAL_STRENGTH_CHANGED = 200;
|
||||
private static final int EVENT_SERVICE_STATE_CHANGED = 300;
|
||||
|
||||
private static final int EVENT_FIX_UPTIME = 500;
|
||||
|
||||
private TelephonyManager mTelephonyManager;
|
||||
private Phone mPhone = null;
|
||||
private PhoneStateIntentReceiver mPhoneStateReceiver;
|
||||
private Resources mRes;
|
||||
private Preference mSignalStrength;
|
||||
private Preference mUptime;
|
||||
private Preference mAwakeTime;
|
||||
|
||||
private static String sUnknown;
|
||||
|
||||
private Preference mBatteryStatus;
|
||||
private Preference mBatteryLevel;
|
||||
|
||||
private Handler mHandler;
|
||||
|
||||
private static class MyHandler extends Handler {
|
||||
private WeakReference<Status> mStatus;
|
||||
|
||||
public MyHandler(Status activity) {
|
||||
mStatus = new WeakReference<Status>(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
Status status = mStatus.get();
|
||||
if (status == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg.what) {
|
||||
case EVENT_SIGNAL_STRENGTH_CHANGED:
|
||||
status.updateSignalStrength();
|
||||
break;
|
||||
|
||||
case EVENT_SERVICE_STATE_CHANGED:
|
||||
ServiceState serviceState = status.mPhoneStateReceiver.getServiceState();
|
||||
status.updateServiceState(serviceState);
|
||||
break;
|
||||
|
||||
case EVENT_FIX_UPTIME:
|
||||
status.updateTimes();
|
||||
sendMessageDelayed(obtainMessage(EVENT_FIX_UPTIME), 1000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BroadcastReceiver mBatteryInfoReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
|
||||
|
||||
int level = intent.getIntExtra("level", 0);
|
||||
int scale = intent.getIntExtra("scale", 100);
|
||||
|
||||
mBatteryLevel.setSummary(String.valueOf(level * 100 / scale) + "%");
|
||||
|
||||
int plugType = intent.getIntExtra("plugged", 0);
|
||||
int status = intent.getIntExtra("status", BatteryManager.BATTERY_STATUS_UNKNOWN);
|
||||
String statusString;
|
||||
if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
|
||||
statusString = getString(R.string.battery_info_status_charging);
|
||||
if (plugType > 0) {
|
||||
statusString = statusString + " " + getString(
|
||||
(plugType == BatteryManager.BATTERY_PLUGGED_AC)
|
||||
? R.string.battery_info_status_charging_ac
|
||||
: R.string.battery_info_status_charging_usb);
|
||||
}
|
||||
} else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) {
|
||||
statusString = getString(R.string.battery_info_status_discharging);
|
||||
} else if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
|
||||
statusString = getString(R.string.battery_info_status_not_charging);
|
||||
} else if (status == BatteryManager.BATTERY_STATUS_FULL) {
|
||||
statusString = getString(R.string.battery_info_status_full);
|
||||
} else {
|
||||
statusString = getString(R.string.battery_info_status_unknown);
|
||||
}
|
||||
mBatteryStatus.setSummary(statusString);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
|
||||
@Override
|
||||
public void onDataConnectionStateChanged(int state) {
|
||||
updateDataState();
|
||||
updateNetworkType();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
mHandler = new MyHandler(this);
|
||||
|
||||
mTelephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
|
||||
|
||||
addPreferencesFromResource(R.xml.device_info_status);
|
||||
mBatteryLevel = findPreference("battery_level");
|
||||
mBatteryStatus = findPreference("battery_status");
|
||||
|
||||
mRes = getResources();
|
||||
if (sUnknown == null) {
|
||||
sUnknown = mRes.getString(R.string.device_info_default);
|
||||
}
|
||||
|
||||
mPhone = PhoneFactory.getDefaultPhone();
|
||||
mSignalStrength = findPreference("signal_strength");
|
||||
mUptime = findPreference("up_time");
|
||||
mAwakeTime = findPreference("awake_time");
|
||||
|
||||
setSummaryText("imei", mPhone.getDeviceId());
|
||||
setSummaryText("imei_sv",
|
||||
((TelephonyManager) getSystemService(TELEPHONY_SERVICE))
|
||||
.getDeviceSoftwareVersion());
|
||||
setSummaryText("imsi", mPhone.getSubscriberId());
|
||||
setSummaryText("number", mPhone.getLine1Number());
|
||||
|
||||
mPhoneStateReceiver = new PhoneStateIntentReceiver(this, mHandler);
|
||||
mPhoneStateReceiver.notifySignalStrength(EVENT_SIGNAL_STRENGTH_CHANGED);
|
||||
mPhoneStateReceiver.notifyServiceState(EVENT_SERVICE_STATE_CHANGED);
|
||||
|
||||
setWifiStatus();
|
||||
setBtStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
mPhoneStateReceiver.registerIntent();
|
||||
registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
|
||||
updateSignalStrength();
|
||||
updateServiceState(mPhone.getServiceState());
|
||||
updateDataState();
|
||||
|
||||
mTelephonyManager.listen(mPhoneStateListener,
|
||||
PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
|
||||
|
||||
mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_FIX_UPTIME), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
mPhoneStateReceiver.unregisterIntent();
|
||||
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
|
||||
unregisterReceiver(mBatteryInfoReceiver);
|
||||
mHandler.removeMessages(EVENT_FIX_UPTIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param preference The key for the Preference item
|
||||
* @param property The system property to fetch
|
||||
* @param alt The default value, if the property doesn't exist
|
||||
*/
|
||||
private void setSummary(String preference, String property, String alt) {
|
||||
try {
|
||||
findPreference(preference).setSummary(
|
||||
SystemProperties.get(property, alt));
|
||||
} catch (RuntimeException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void setSummaryText(String preference, String text) {
|
||||
if (text != null) {
|
||||
findPreference(preference).setSummary(text);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNetworkType() {
|
||||
// Whether EDGE, UMTS, etc...
|
||||
setSummary("network_type", TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE, sUnknown);
|
||||
}
|
||||
|
||||
private void updateDataState() {
|
||||
int state = mTelephonyManager.getDataState();
|
||||
String display = mRes.getString(R.string.radioInfo_unknown);
|
||||
|
||||
switch (state) {
|
||||
case TelephonyManager.DATA_CONNECTED:
|
||||
display = mRes.getString(R.string.radioInfo_data_connected);
|
||||
break;
|
||||
case TelephonyManager.DATA_SUSPENDED:
|
||||
display = mRes.getString(R.string.radioInfo_data_suspended);
|
||||
break;
|
||||
case TelephonyManager.DATA_CONNECTING:
|
||||
display = mRes.getString(R.string.radioInfo_data_connecting);
|
||||
break;
|
||||
case TelephonyManager.DATA_DISCONNECTED:
|
||||
display = mRes.getString(R.string.radioInfo_data_disconnected);
|
||||
break;
|
||||
}
|
||||
|
||||
setSummaryText("data_state", display);
|
||||
}
|
||||
|
||||
private void updateServiceState(ServiceState serviceState) {
|
||||
int state = serviceState.getState();
|
||||
String display = mRes.getString(R.string.radioInfo_unknown);
|
||||
|
||||
switch (state) {
|
||||
case ServiceState.STATE_IN_SERVICE:
|
||||
display = mRes.getString(R.string.radioInfo_service_in);
|
||||
break;
|
||||
case ServiceState.STATE_OUT_OF_SERVICE:
|
||||
case ServiceState.STATE_EMERGENCY_ONLY:
|
||||
display = mRes.getString(R.string.radioInfo_service_out);
|
||||
break;
|
||||
case ServiceState.STATE_POWER_OFF:
|
||||
display = mRes.getString(R.string.radioInfo_service_off);
|
||||
break;
|
||||
}
|
||||
|
||||
setSummaryText("service_state", display);
|
||||
|
||||
if (serviceState.getRoaming()) {
|
||||
setSummaryText("roaming_state", mRes.getString(R.string.radioInfo_roaming_in));
|
||||
} else {
|
||||
setSummaryText("roaming_state", mRes.getString(R.string.radioInfo_roaming_not));
|
||||
}
|
||||
setSummaryText("operator_name", serviceState.getOperatorAlphaLong());
|
||||
}
|
||||
|
||||
void updateSignalStrength() {
|
||||
int state =
|
||||
mPhoneStateReceiver.getServiceState().getState();
|
||||
Resources r = getResources();
|
||||
|
||||
if ((ServiceState.STATE_OUT_OF_SERVICE == state) ||
|
||||
(ServiceState.STATE_POWER_OFF == state)) {
|
||||
mSignalStrength.setSummary("0");
|
||||
}
|
||||
|
||||
int signalDbm = mPhoneStateReceiver.getSignalStrengthDbm();
|
||||
|
||||
if (-1 == signalDbm) signalDbm = 0;
|
||||
|
||||
int signalAsu = mPhoneStateReceiver.getSignalStrength();
|
||||
|
||||
if (-1 == signalAsu) signalAsu = 0;
|
||||
|
||||
mSignalStrength.setSummary(String.valueOf(signalDbm) + " "
|
||||
+ r.getString(R.string.radioInfo_display_dbm) + " "
|
||||
+ String.valueOf(signalAsu) + " "
|
||||
+ r.getString(R.string.radioInfo_display_asu));
|
||||
}
|
||||
|
||||
private void setWifiStatus() {
|
||||
WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
|
||||
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
|
||||
|
||||
Preference wifiMacAddressPref = findPreference(KEY_WIFI_MAC_ADDRESS);
|
||||
String macAddress = wifiInfo == null ? null : wifiInfo.getMacAddress();
|
||||
wifiMacAddressPref.setSummary(!TextUtils.isEmpty(macAddress) ? macAddress
|
||||
: getString(R.string.status_unavailable));
|
||||
}
|
||||
|
||||
private void setBtStatus() {
|
||||
BluetoothDevice bluetooth = (BluetoothDevice) getSystemService(BLUETOOTH_SERVICE);
|
||||
Preference btAddressPref = findPreference(KEY_BT_ADDRESS);
|
||||
|
||||
if (bluetooth == null) {
|
||||
// device not BT capable
|
||||
getPreferenceScreen().removePreference(btAddressPref);
|
||||
} else {
|
||||
String address = bluetooth.isEnabled() ? bluetooth.getAddress() : null;
|
||||
btAddressPref.setSummary(!TextUtils.isEmpty(address) ? address
|
||||
: getString(R.string.status_unavailable));
|
||||
}
|
||||
}
|
||||
|
||||
void updateTimes() {
|
||||
long at = SystemClock.uptimeMillis() / 1000;
|
||||
long ut = SystemClock.elapsedRealtime() / 1000;
|
||||
long st = ut - at;
|
||||
|
||||
if (ut == 0) {
|
||||
ut = 1;
|
||||
}
|
||||
|
||||
mUptime.setSummary(convert(ut));
|
||||
mAwakeTime.setSummary(convert(at) + " (" + (((1000 * at / ut) + 5) / 10) + "%)");
|
||||
}
|
||||
|
||||
private String pad(int n) {
|
||||
if (n >= 10) {
|
||||
return String.valueOf(n);
|
||||
} else {
|
||||
return "0" + String.valueOf(n);
|
||||
}
|
||||
}
|
||||
|
||||
private String convert(long t) {
|
||||
int s = (int)(t % 60);
|
||||
int m = (int)((t / 60) % 60);
|
||||
int h = (int)((t / 3600));
|
||||
|
||||
return h + ":" + pad(m) + ":" + pad(s);
|
||||
}
|
||||
}
|
||||
331
src/com/android/settings/quicklaunch/BookmarkPicker.java
Normal file
331
src/com/android/settings/quicklaunch/BookmarkPicker.java
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.quicklaunch;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import android.app.ListActivity;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SimpleAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Activity to pick a bookmark that will be returned to the caller.
|
||||
* <p>
|
||||
* Currently, bookmarks are either:
|
||||
* <li> Activities that are in the launcher
|
||||
* <li> Activities that are within an app that is capable of being launched with
|
||||
* the {@link Intent#ACTION_CREATE_SHORTCUT}.
|
||||
*/
|
||||
public class BookmarkPicker extends ListActivity implements SimpleAdapter.ViewBinder {
|
||||
|
||||
private static final String TAG = "BookmarkPicker";
|
||||
|
||||
/** Extra in the returned intent from this activity. */
|
||||
public static final String EXTRA_TITLE = "com.android.settings.quicklaunch.TITLE";
|
||||
|
||||
/** Extra that should be provided, and will be returned. */
|
||||
public static final String EXTRA_SHORTCUT = "com.android.settings.quicklaunch.SHORTCUT";
|
||||
|
||||
/**
|
||||
* The request code for the screen to create a bookmark that is WITHIN an
|
||||
* application. For example, Gmail can return a bookmark for the inbox
|
||||
* folder.
|
||||
*/
|
||||
private static final int REQUEST_CREATE_SHORTCUT = 1;
|
||||
|
||||
/** Intent used to get all the activities that are launch-able */
|
||||
private static Intent sLaunchIntent;
|
||||
/** Intent used to get all the activities that are {@link #REQUEST_CREATE_SHORTCUT}-able */
|
||||
private static Intent sShortcutIntent;
|
||||
|
||||
/**
|
||||
* List of ResolveInfo for activities that we can bookmark (either directly
|
||||
* to the activity, or by launching the activity and it returning a bookmark
|
||||
* WITHIN that application).
|
||||
*/
|
||||
private List<ResolveInfo> mResolveList;
|
||||
|
||||
// List adapter stuff
|
||||
private static final String KEY_TITLE = "TITLE";
|
||||
private static final String KEY_RESOLVE_INFO = "RESOLVE_INFO";
|
||||
private static final String sKeys[] = new String[] { KEY_TITLE, KEY_RESOLVE_INFO };
|
||||
private static final int sResourceIds[] = new int[] { R.id.title, R.id.icon };
|
||||
private SimpleAdapter mMyAdapter;
|
||||
|
||||
/** Display those activities that are launch-able */
|
||||
private static final int DISPLAY_MODE_LAUNCH = 0;
|
||||
/** Display those activities that are able to have bookmarks WITHIN the application */
|
||||
private static final int DISPLAY_MODE_SHORTCUT = 1;
|
||||
private int mDisplayMode = DISPLAY_MODE_LAUNCH;
|
||||
|
||||
private Handler mUiHandler = new Handler();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
updateListAndAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
menu.add(0, DISPLAY_MODE_LAUNCH, 0, R.string.quick_launch_display_mode_applications)
|
||||
.setIcon(R.drawable.ic_menu_archive);
|
||||
menu.add(0, DISPLAY_MODE_SHORTCUT, 0, R.string.quick_launch_display_mode_shortcuts)
|
||||
.setIcon(R.drawable.ic_menu_goto);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
menu.findItem(DISPLAY_MODE_LAUNCH).setVisible(mDisplayMode != DISPLAY_MODE_LAUNCH);
|
||||
menu.findItem(DISPLAY_MODE_SHORTCUT).setVisible(mDisplayMode != DISPLAY_MODE_SHORTCUT);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
|
||||
switch (item.getItemId()) {
|
||||
|
||||
case DISPLAY_MODE_LAUNCH:
|
||||
mDisplayMode = DISPLAY_MODE_LAUNCH;
|
||||
break;
|
||||
|
||||
case DISPLAY_MODE_SHORTCUT:
|
||||
mDisplayMode = DISPLAY_MODE_SHORTCUT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
updateListAndAdapter();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ensureIntents() {
|
||||
if (sLaunchIntent == null) {
|
||||
sLaunchIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
sShortcutIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be called from the UI thread.
|
||||
*/
|
||||
private void updateListAndAdapter() {
|
||||
// Get the activities in a separate thread
|
||||
new Thread("data updater") {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (BookmarkPicker.this) {
|
||||
/*
|
||||
* Don't touch any of the lists that are being used by the
|
||||
* adapter in this thread!
|
||||
*/
|
||||
ArrayList<ResolveInfo> newResolveList = new ArrayList<ResolveInfo>();
|
||||
ArrayList<Map<String, ?>> newAdapterList = new ArrayList<Map<String, ?>>();
|
||||
|
||||
fillResolveList(newResolveList);
|
||||
Collections.sort(newResolveList,
|
||||
new ResolveInfo.DisplayNameComparator(getPackageManager()));
|
||||
|
||||
fillAdapterList(newAdapterList, newResolveList);
|
||||
|
||||
updateAdapterToUseNewLists(newAdapterList, newResolveList);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
private void updateAdapterToUseNewLists(final ArrayList<Map<String, ?>> newAdapterList,
|
||||
final ArrayList<ResolveInfo> newResolveList) {
|
||||
// Post this back on the UI thread
|
||||
mUiHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
/*
|
||||
* SimpleAdapter does not support changing the lists after it
|
||||
* has been created. We just create a new instance.
|
||||
*/
|
||||
mMyAdapter = createResolveAdapter(newAdapterList);
|
||||
mResolveList = newResolveList;
|
||||
setListAdapter(mMyAdapter);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all activities matching our current display mode.
|
||||
*
|
||||
* @param list The list to fill.
|
||||
*/
|
||||
private void fillResolveList(List<ResolveInfo> list) {
|
||||
ensureIntents();
|
||||
PackageManager pm = getPackageManager();
|
||||
list.clear();
|
||||
|
||||
if (mDisplayMode == DISPLAY_MODE_LAUNCH) {
|
||||
list.addAll(pm.queryIntentActivities(sLaunchIntent, 0));
|
||||
} else if (mDisplayMode == DISPLAY_MODE_SHORTCUT) {
|
||||
list.addAll(pm.queryIntentActivities(sShortcutIntent, 0));
|
||||
}
|
||||
}
|
||||
|
||||
private SimpleAdapter createResolveAdapter(List<Map<String, ?>> list) {
|
||||
SimpleAdapter adapter = new SimpleAdapter(this, list,
|
||||
R.layout.bookmark_picker_item, sKeys, sResourceIds);
|
||||
adapter.setViewBinder(this);
|
||||
return adapter;
|
||||
}
|
||||
|
||||
private void fillAdapterList(List<Map<String, ?>> list,
|
||||
List<ResolveInfo> resolveList) {
|
||||
list.clear();
|
||||
int resolveListSize = resolveList.size();
|
||||
for (int i = 0; i < resolveListSize; i++) {
|
||||
ResolveInfo info = resolveList.get(i);
|
||||
/*
|
||||
* Simple adapter craziness. For each item, we need to create a map
|
||||
* from a key to its value (the value can be any object--the view
|
||||
* binder will take care of filling the View with a representation
|
||||
* of that object).
|
||||
*/
|
||||
Map<String, Object> map = new TreeMap<String, Object>();
|
||||
map.put(KEY_TITLE, getResolveInfoTitle(info));
|
||||
map.put(KEY_RESOLVE_INFO, info);
|
||||
list.add(map);
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the title for a resolve info. */
|
||||
private String getResolveInfoTitle(ResolveInfo info) {
|
||||
CharSequence label = info.loadLabel(getPackageManager());
|
||||
if (label == null) label = info.activityInfo.name;
|
||||
return label != null ? label.toString() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
if (position >= mResolveList.size()) return;
|
||||
|
||||
ResolveInfo info = mResolveList.get(position);
|
||||
|
||||
switch (mDisplayMode) {
|
||||
|
||||
case DISPLAY_MODE_LAUNCH:
|
||||
// We can go ahead and return the clicked info's intent
|
||||
Intent intent = getIntentForResolveInfo(info, Intent.ACTION_MAIN);
|
||||
intent.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
finish(intent, getResolveInfoTitle(info));
|
||||
break;
|
||||
|
||||
case DISPLAY_MODE_SHORTCUT:
|
||||
// Start the shortcut activity so the user can pick the actual intent
|
||||
// (example: Gmail's shortcut activity shows a list of mailboxes)
|
||||
startShortcutActivity(info);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Intent getIntentForResolveInfo(ResolveInfo info, String action) {
|
||||
Intent intent = new Intent(action);
|
||||
ActivityInfo ai = info.activityInfo;
|
||||
intent.setClassName(ai.packageName, ai.name);
|
||||
return intent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts an activity to get a shortcut.
|
||||
* <p>
|
||||
* For example, Gmail has an activity that lists the available labels. It
|
||||
* returns a shortcut intent for going directly to this label.
|
||||
*/
|
||||
private void startShortcutActivity(ResolveInfo info) {
|
||||
Intent intent = getIntentForResolveInfo(info, Intent.ACTION_CREATE_SHORTCUT);
|
||||
startActivityForResult(intent, REQUEST_CREATE_SHORTCUT);
|
||||
|
||||
// Will get a callback to onActivityResult
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode != RESULT_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (requestCode) {
|
||||
|
||||
case REQUEST_CREATE_SHORTCUT:
|
||||
if (data != null) {
|
||||
finish((Intent) data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT),
|
||||
data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the activity and returns the given data.
|
||||
*/
|
||||
private void finish(Intent intent, String title) {
|
||||
// Give back what was given to us (it will have the shortcut, for example)
|
||||
intent.putExtras(getIntent());
|
||||
// Put our information
|
||||
intent.putExtra(EXTRA_TITLE, title);
|
||||
setResult(RESULT_OK, intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean setViewValue(View view, Object data, String textRepresentation) {
|
||||
if (view.getId() == R.id.icon) {
|
||||
Drawable icon = ((ResolveInfo) data).loadIcon(getPackageManager());
|
||||
if (icon != null) {
|
||||
((ImageView) view).setImageDrawable(icon);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
347
src/com/android/settings/quicklaunch/QuickLaunchSettings.java
Normal file
347
src/com/android/settings/quicklaunch/QuickLaunchSettings.java
Normal file
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.quicklaunch;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.database.ContentObserver;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.provider.Settings.Bookmarks;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.KeyCharacterMap;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
|
||||
/**
|
||||
* Settings activity for quick launch.
|
||||
* <p>
|
||||
* Shows a list of possible shortcuts, the current application each is bound to,
|
||||
* and allows choosing a new bookmark for a shortcut.
|
||||
*/
|
||||
public class QuickLaunchSettings extends PreferenceActivity implements
|
||||
AdapterView.OnItemLongClickListener, DialogInterface.OnClickListener {
|
||||
|
||||
private static final String TAG = "QuickLaunchSettings";
|
||||
|
||||
private static final String KEY_SHORTCUT_CATEGORY = "shortcut_category";
|
||||
|
||||
private static final int DIALOG_CLEAR_SHORTCUT = 0;
|
||||
|
||||
private static final int REQUEST_PICK_BOOKMARK = 1;
|
||||
|
||||
private static final int COLUMN_SHORTCUT = 0;
|
||||
private static final int COLUMN_TITLE = 1;
|
||||
private static final String[] sProjection = new String[] {
|
||||
Bookmarks.SHORTCUT, Bookmarks.TITLE
|
||||
};
|
||||
private static final String sShortcutSelection = Bookmarks.SHORTCUT + "=?";
|
||||
|
||||
private Handler mUiHandler = new Handler();
|
||||
|
||||
private static final String DEFAULT_BOOKMARK_FOLDER = "@default";
|
||||
/** Cursor for Bookmarks provider. */
|
||||
private Cursor mBookmarksCursor;
|
||||
/** Listens for changes to Bookmarks provider. */
|
||||
private BookmarksObserver mBookmarksObserver;
|
||||
/** Used to keep track of which shortcuts have bookmarks. */
|
||||
private SparseBooleanArray mBookmarkedShortcuts;
|
||||
|
||||
/** Preference category to hold the shortcut preferences. */
|
||||
private PreferenceCategory mShortcutCategory;
|
||||
/** Mapping of a shortcut to its preference. */
|
||||
private SparseArray<ShortcutPreference> mShortcutToPreference;
|
||||
|
||||
/** The bookmark title of the shortcut that is being cleared. */
|
||||
private CharSequence mClearDialogBookmarkTitle;
|
||||
private static final String CLEAR_DIALOG_BOOKMARK_TITLE = "CLEAR_DIALOG_BOOKMARK_TITLE";
|
||||
/** The shortcut that is being cleared. */
|
||||
private char mClearDialogShortcut;
|
||||
private static final String CLEAR_DIALOG_SHORTCUT = "CLEAR_DIALOG_SHORTCUT";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.quick_launch_settings);
|
||||
|
||||
mShortcutCategory = (PreferenceCategory) findPreference(KEY_SHORTCUT_CATEGORY);
|
||||
mShortcutToPreference = new SparseArray<ShortcutPreference>();
|
||||
mBookmarksObserver = new BookmarksObserver(mUiHandler);
|
||||
initShortcutPreferences();
|
||||
mBookmarksCursor = managedQuery(Bookmarks.CONTENT_URI, sProjection, null, null);
|
||||
getListView().setOnItemLongClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
getContentResolver().registerContentObserver(Bookmarks.CONTENT_URI, true,
|
||||
mBookmarksObserver);
|
||||
refreshShortcuts();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
getContentResolver().unregisterContentObserver(mBookmarksObserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle state) {
|
||||
super.onRestoreInstanceState(state);
|
||||
|
||||
// Restore the clear dialog's info
|
||||
mClearDialogBookmarkTitle = state.getString(CLEAR_DIALOG_BOOKMARK_TITLE);
|
||||
mClearDialogShortcut = (char) state.getInt(CLEAR_DIALOG_SHORTCUT, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
// Save the clear dialog's info
|
||||
outState.putCharSequence(CLEAR_DIALOG_BOOKMARK_TITLE, mClearDialogBookmarkTitle);
|
||||
outState.putInt(CLEAR_DIALOG_SHORTCUT, mClearDialogShortcut);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog onCreateDialog(int id) {
|
||||
switch (id) {
|
||||
|
||||
case DIALOG_CLEAR_SHORTCUT: {
|
||||
// Create the dialog for clearing a shortcut
|
||||
return new AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.quick_launch_clear_dialog_title))
|
||||
.setIcon(R.drawable.ic_dialog_alert)
|
||||
.setMessage(getString(R.string.quick_launch_clear_dialog_message,
|
||||
mClearDialogShortcut, mClearDialogBookmarkTitle))
|
||||
.setPositiveButton(R.string.quick_launch_clear_ok_button, this)
|
||||
.setNegativeButton(R.string.quick_launch_clear_cancel_button, this)
|
||||
.create();
|
||||
}
|
||||
}
|
||||
|
||||
return super.onCreateDialog(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareDialog(int id, Dialog dialog) {
|
||||
switch (id) {
|
||||
|
||||
case DIALOG_CLEAR_SHORTCUT: {
|
||||
AlertDialog alertDialog = (AlertDialog) dialog;
|
||||
alertDialog.setMessage(getString(R.string.quick_launch_clear_dialog_message,
|
||||
mClearDialogShortcut, mClearDialogBookmarkTitle));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showClearDialog(ShortcutPreference pref) {
|
||||
|
||||
if (!pref.hasBookmark()) return;
|
||||
|
||||
mClearDialogBookmarkTitle = pref.getTitle();
|
||||
mClearDialogShortcut = pref.getShortcut();
|
||||
showDialog(DIALOG_CLEAR_SHORTCUT);
|
||||
}
|
||||
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (mClearDialogShortcut > 0 && which == AlertDialog.BUTTON1) {
|
||||
// Clear the shortcut
|
||||
clearShortcut(mClearDialogShortcut);
|
||||
}
|
||||
mClearDialogBookmarkTitle = null;
|
||||
mClearDialogShortcut = 0;
|
||||
}
|
||||
|
||||
private void clearShortcut(char shortcut) {
|
||||
getContentResolver().delete(Bookmarks.CONTENT_URI, sShortcutSelection,
|
||||
new String[] { String.valueOf((int) shortcut) });
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
|
||||
if (!(preference instanceof ShortcutPreference)) return false;
|
||||
|
||||
// Open the screen to pick a bookmark for this shortcut
|
||||
ShortcutPreference pref = (ShortcutPreference) preference;
|
||||
Intent intent = new Intent(this, BookmarkPicker.class);
|
||||
intent.putExtra(BookmarkPicker.EXTRA_SHORTCUT, pref.getShortcut());
|
||||
startActivityForResult(intent, REQUEST_PICK_BOOKMARK);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onItemLongClick(AdapterView parent, View view, int position, long id) {
|
||||
|
||||
// Open the clear shortcut dialog
|
||||
Preference pref = (Preference) getPreferenceScreen().getRootAdapter().getItem(position);
|
||||
if (!(pref instanceof ShortcutPreference)) return false;
|
||||
showClearDialog((ShortcutPreference) pref);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode != RESULT_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (requestCode == REQUEST_PICK_BOOKMARK) {
|
||||
|
||||
// Returned from the 'pick bookmark for this shortcut' screen
|
||||
if (data == null) {
|
||||
Log.w(TAG, "Result from bookmark picker does not have an intent.");
|
||||
return;
|
||||
}
|
||||
|
||||
String title = data.getStringExtra(BookmarkPicker.EXTRA_TITLE);
|
||||
char shortcut = data.getCharExtra(BookmarkPicker.EXTRA_SHORTCUT, (char) 0);
|
||||
updateShortcut(shortcut, title, data);
|
||||
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateShortcut(char shortcut, String title, Intent intent) {
|
||||
|
||||
// Update the bookmark for a shortcut
|
||||
Bookmarks.add(getContentResolver(), intent, title.toString(), DEFAULT_BOOKMARK_FOLDER,
|
||||
shortcut, 0);
|
||||
}
|
||||
|
||||
private ShortcutPreference getOrCreatePreference(char shortcut) {
|
||||
ShortcutPreference pref = mShortcutToPreference.get(shortcut);
|
||||
if (pref != null) {
|
||||
return pref;
|
||||
} else {
|
||||
Log.w(TAG, "Unknown shortcut '" + shortcut + "', creating preference anyway");
|
||||
return createPreference(shortcut);
|
||||
}
|
||||
}
|
||||
|
||||
private ShortcutPreference createPreference(char shortcut) {
|
||||
ShortcutPreference pref = new ShortcutPreference(QuickLaunchSettings.this, shortcut);
|
||||
mShortcutCategory.addPreference(pref);
|
||||
mShortcutToPreference.put(shortcut, pref);
|
||||
return pref;
|
||||
}
|
||||
|
||||
private void initShortcutPreferences() {
|
||||
|
||||
/** Whether the shortcut has been seen already. The array index is the shortcut. */
|
||||
SparseBooleanArray shortcutSeen = new SparseBooleanArray();
|
||||
KeyCharacterMap keyMap = KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD);
|
||||
|
||||
// Go through all the key codes and create a preference for the appropriate keys
|
||||
for (int keyCode = KeyEvent.MAX_KEYCODE - 1; keyCode >= 0; keyCode--) {
|
||||
// Get the label for the primary char on the key that produces this key code
|
||||
char shortcut = (char) Character.toLowerCase(keyMap.getDisplayLabel(keyCode));
|
||||
if (shortcut == 0 || shortcutSeen.get(shortcut, false)) continue;
|
||||
// TODO: need a to tell if the current keyboard can produce this key code, for now
|
||||
// only allow the letter or digits
|
||||
if (!Character.isLetterOrDigit(shortcut)) continue;
|
||||
shortcutSeen.put(shortcut, true);
|
||||
|
||||
createPreference(shortcut);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void refreshShortcuts() {
|
||||
Cursor c = mBookmarksCursor;
|
||||
if (c == null) {
|
||||
// Haven't finished querying yet
|
||||
return;
|
||||
}
|
||||
|
||||
if (!c.requery()) {
|
||||
Log.e(TAG, "Could not requery cursor when refreshing shortcuts.");
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* We use the previous bookmarked shortcuts array to filter out those
|
||||
* shortcuts that had bookmarks before this method call, and don't after
|
||||
* (so we can set the preferences to be without bookmarks).
|
||||
*/
|
||||
SparseBooleanArray noLongerBookmarkedShortcuts = mBookmarkedShortcuts;
|
||||
SparseBooleanArray newBookmarkedShortcuts = new SparseBooleanArray();
|
||||
while (c.moveToNext()) {
|
||||
char shortcut = Character.toLowerCase((char) c.getInt(COLUMN_SHORTCUT));
|
||||
if (shortcut == 0) continue;
|
||||
|
||||
ShortcutPreference pref = getOrCreatePreference(shortcut);
|
||||
pref.setTitle(c.getString(COLUMN_TITLE));
|
||||
pref.setSummary(getString(R.string.quick_launch_shortcut,
|
||||
String.valueOf(shortcut)));
|
||||
pref.setHasBookmark(true);
|
||||
|
||||
newBookmarkedShortcuts.put(shortcut, true);
|
||||
if (noLongerBookmarkedShortcuts != null) {
|
||||
// After this loop, the shortcuts with value true in this array
|
||||
// will no longer have bookmarks
|
||||
noLongerBookmarkedShortcuts.put(shortcut, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (noLongerBookmarkedShortcuts != null) {
|
||||
for (int i = noLongerBookmarkedShortcuts.size() - 1; i >= 0; i--) {
|
||||
if (noLongerBookmarkedShortcuts.valueAt(i)) {
|
||||
// True, so there is no longer a bookmark for this shortcut
|
||||
char shortcut = (char) noLongerBookmarkedShortcuts.keyAt(i);
|
||||
ShortcutPreference pref = mShortcutToPreference.get(shortcut);
|
||||
if (pref != null) {
|
||||
pref.setHasBookmark(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mBookmarkedShortcuts = newBookmarkedShortcuts;
|
||||
|
||||
c.deactivate();
|
||||
}
|
||||
|
||||
private class BookmarksObserver extends ContentObserver {
|
||||
|
||||
public BookmarksObserver(Handler handler) {
|
||||
super(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
super.onChange(selfChange);
|
||||
|
||||
refreshShortcuts();
|
||||
}
|
||||
}
|
||||
}
|
||||
151
src/com/android/settings/quicklaunch/ShortcutPreference.java
Normal file
151
src/com/android/settings/quicklaunch/ShortcutPreference.java
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.quicklaunch;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.preference.Preference;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* Preference type for a shortcut in {@link QuickLaunchSettings}.
|
||||
*/
|
||||
public class ShortcutPreference extends Preference implements Comparable<Preference> {
|
||||
|
||||
private static Object sStaticVarsLock = new Object();
|
||||
|
||||
// These static fields are used across all instances of ShortcutPreference.
|
||||
// There will be many ShortcutPreference instances (~36 for US).
|
||||
private static String STRING_ASSIGN_APPLICATION;
|
||||
private static String STRING_NO_SHORTCUT;
|
||||
|
||||
private static int sDimAlpha;
|
||||
private static ColorStateList sRegularTitleColor;
|
||||
private static ColorStateList sDimTitleColor;
|
||||
private static ColorStateList sRegularSummaryColor;
|
||||
private static ColorStateList sDimSummaryColor;
|
||||
|
||||
private char mShortcut;
|
||||
private boolean mHasBookmark;
|
||||
|
||||
public ShortcutPreference(Context context, char shortcut) {
|
||||
super(context);
|
||||
|
||||
synchronized (sStaticVarsLock) {
|
||||
// Init statics. This should only happen for the first ShortcutPreference created,
|
||||
// the rest will already have them initialized.
|
||||
if (STRING_ASSIGN_APPLICATION == null) {
|
||||
STRING_ASSIGN_APPLICATION = context.getString(R.string.quick_launch_assign_application);
|
||||
STRING_NO_SHORTCUT = context.getString(R.string.quick_launch_no_shortcut);
|
||||
|
||||
TypedValue outValue = new TypedValue();
|
||||
context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, outValue, true);
|
||||
sDimAlpha = (int) (outValue.getFloat() * 255);
|
||||
}
|
||||
}
|
||||
|
||||
mShortcut = shortcut;
|
||||
|
||||
setWidgetLayoutResource(R.layout.preference_widget_shortcut);
|
||||
}
|
||||
|
||||
public char getShortcut() {
|
||||
return mShortcut;
|
||||
}
|
||||
|
||||
public void setShortcut(char shortcut) {
|
||||
if (shortcut != mShortcut) {
|
||||
mShortcut = shortcut;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasBookmark() {
|
||||
return mHasBookmark;
|
||||
}
|
||||
|
||||
public void setHasBookmark(boolean hasBookmark) {
|
||||
if (hasBookmark != mHasBookmark) {
|
||||
mHasBookmark = hasBookmark;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getTitle() {
|
||||
return mHasBookmark ? super.getTitle() : STRING_ASSIGN_APPLICATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
return mHasBookmark ? super.getSummary() : STRING_NO_SHORTCUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindView(View view) {
|
||||
super.onBindView(view);
|
||||
|
||||
TextView shortcutView = (TextView) view.findViewById(R.id.shortcut);
|
||||
if (shortcutView != null) {
|
||||
shortcutView.setText(String.valueOf(mShortcut));
|
||||
}
|
||||
|
||||
TextView titleView = (TextView) view.findViewById(android.R.id.title);
|
||||
|
||||
synchronized (sStaticVarsLock) {
|
||||
if (sRegularTitleColor == null) {
|
||||
sRegularTitleColor = titleView.getTextColors();
|
||||
sDimTitleColor = sRegularTitleColor.withAlpha(sDimAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
ColorStateList color = mHasBookmark ? sRegularTitleColor : sDimTitleColor;
|
||||
if (color != null) {
|
||||
titleView.setTextColor(color);
|
||||
}
|
||||
|
||||
TextView summaryView = (TextView) view.findViewById(android.R.id.summary);
|
||||
|
||||
synchronized (sStaticVarsLock) {
|
||||
if (sRegularSummaryColor == null) {
|
||||
sRegularSummaryColor = summaryView.getTextColors();
|
||||
sDimSummaryColor = sRegularSummaryColor.withAlpha(sDimAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
color = mHasBookmark ? sRegularSummaryColor : sDimSummaryColor;
|
||||
if (color != null) {
|
||||
summaryView.setTextColor(color);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int compareTo(Preference another) {
|
||||
if (!(another instanceof ShortcutPreference)) return super.compareTo(another);
|
||||
|
||||
// Letters before digits
|
||||
char other = ((ShortcutPreference) another).mShortcut;
|
||||
if (Character.isDigit(mShortcut) && Character.isLetter(other)) return 1;
|
||||
else if (Character.isDigit(other) && Character.isLetter(mShortcut)) return -1;
|
||||
else return mShortcut - other;
|
||||
}
|
||||
|
||||
}
|
||||
607
src/com/android/settings/wifi/AccessPointDialog.java
Normal file
607
src/com/android/settings/wifi/AccessPointDialog.java
Normal file
@@ -0,0 +1,607 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.PasswordTransformationMethod;
|
||||
import android.text.method.TransformationMethod;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TableLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class AccessPointDialog extends AlertDialog implements DialogInterface.OnClickListener,
|
||||
AdapterView.OnItemSelectedListener, View.OnClickListener {
|
||||
|
||||
private static final String TAG = "AccessPointDialog";
|
||||
private static final String INSTANCE_KEY_ACCESS_POINT_STATE =
|
||||
"com.android.settings.wifi.AccessPointDialog:accessPointState";
|
||||
private static final String INSTANCE_KEY_MODE =
|
||||
"com.android.settings.wifi.AccessPointDialog:mode";
|
||||
private static final String INSTANCE_KEY_CUSTOM_TITLE =
|
||||
"com.android.settings.wifi.AccessPointDialog:customTitle";
|
||||
private static final String INSTANCE_KEY_AUTO_SECURITY_ALLOWED =
|
||||
"com.android.settings.wifi.AccessPointDialog:autoSecurityAllowed";
|
||||
|
||||
private static final int POSITIVE_BUTTON = BUTTON1;
|
||||
private static final int NEGATIVE_BUTTON = BUTTON2;
|
||||
private static final int NEUTRAL_BUTTON = BUTTON3;
|
||||
|
||||
/** The dialog should show info connectivity functionality */
|
||||
public static final int MODE_INFO = 0;
|
||||
/** The dialog should configure the detailed AP properties */
|
||||
public static final int MODE_CONFIGURE = 1;
|
||||
/** The dialog should have the password field and connect/cancel */
|
||||
public static final int MODE_RETRY_PASSWORD = 2;
|
||||
|
||||
// These should be matched with the XML. Both arrays in XML depend on this
|
||||
// ordering!
|
||||
private static final int SECURITY_AUTO = 0;
|
||||
private static final int SECURITY_NONE = 1;
|
||||
private static final int SECURITY_WEP = 2;
|
||||
private static final int SECURITY_WPA_PERSONAL = 3;
|
||||
private static final int SECURITY_WPA2_PERSONAL = 4;
|
||||
|
||||
private static final int[] WEP_TYPE_VALUES = {
|
||||
AccessPointState.WEP_PASSWORD_AUTO, AccessPointState.WEP_PASSWORD_ASCII,
|
||||
AccessPointState.WEP_PASSWORD_HEX
|
||||
};
|
||||
|
||||
// Button positions, default to impossible values
|
||||
private int mConnectButtonPos = Integer.MAX_VALUE;
|
||||
private int mForgetButtonPos = Integer.MAX_VALUE;
|
||||
private int mSaveButtonPos = Integer.MAX_VALUE;
|
||||
|
||||
// Client configurable items. Generally, these should be saved in instance state
|
||||
private int mMode = MODE_INFO;
|
||||
private boolean mAutoSecurityAllowed = true;
|
||||
private CharSequence mCustomTitle;
|
||||
// This does not need to be saved in instance state.
|
||||
private WifiLayer mWifiLayer;
|
||||
private AccessPointState mState;
|
||||
|
||||
// General views
|
||||
private View mView;
|
||||
private TextView mPasswordText;
|
||||
private EditText mPasswordEdit;
|
||||
private CheckBox mShowPasswordCheckBox;
|
||||
|
||||
// Info-specific views
|
||||
private ViewGroup mTable;
|
||||
|
||||
// Configure-specific views
|
||||
private EditText mSsidEdit;
|
||||
private Spinner mSecuritySpinner;
|
||||
private Spinner mWepTypeSpinner;
|
||||
|
||||
public AccessPointDialog(Context context, WifiLayer wifiLayer) {
|
||||
super(context);
|
||||
|
||||
mWifiLayer = wifiLayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
onLayout();
|
||||
onFill();
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
// Set to a class loader that can find AccessPointState
|
||||
savedInstanceState.setClassLoader(getClass().getClassLoader());
|
||||
|
||||
mState = savedInstanceState.getParcelable(INSTANCE_KEY_ACCESS_POINT_STATE);
|
||||
mState.setContext(getContext());
|
||||
|
||||
mMode = savedInstanceState.getInt(INSTANCE_KEY_MODE, mMode);
|
||||
mAutoSecurityAllowed = savedInstanceState.getBoolean(INSTANCE_KEY_AUTO_SECURITY_ALLOWED,
|
||||
mAutoSecurityAllowed);
|
||||
mCustomTitle = savedInstanceState.getCharSequence(INSTANCE_KEY_CUSTOM_TITLE);
|
||||
if (mCustomTitle != null) {
|
||||
setTitle(mCustomTitle);
|
||||
}
|
||||
|
||||
// This is called last since it depends on the above values
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
|
||||
if (mShowPasswordCheckBox != null) {
|
||||
// Restore the show-password-state on the edit text
|
||||
setShowPassword(mShowPasswordCheckBox.isChecked());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle onSaveInstanceState() {
|
||||
Bundle bundle = super.onSaveInstanceState();
|
||||
bundle.putParcelable(INSTANCE_KEY_ACCESS_POINT_STATE, mState);
|
||||
bundle.putInt(INSTANCE_KEY_MODE, mMode);
|
||||
bundle.putBoolean(INSTANCE_KEY_AUTO_SECURITY_ALLOWED, mAutoSecurityAllowed);
|
||||
bundle.putCharSequence(INSTANCE_KEY_CUSTOM_TITLE, mCustomTitle);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets state to show in this dialog.
|
||||
*
|
||||
* @param state The state.
|
||||
*/
|
||||
public void setState(AccessPointState state) {
|
||||
mState = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the dialog mode.
|
||||
* @param mode One of {@link #MODE_CONFIGURE} or {@link #MODE_INFO}
|
||||
*/
|
||||
public void setMode(int mode) {
|
||||
mMode = mode;
|
||||
}
|
||||
|
||||
public void setAutoSecurityAllowed(boolean autoSecurityAllowed) {
|
||||
mAutoSecurityAllowed = autoSecurityAllowed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(CharSequence title) {
|
||||
super.setTitle(title);
|
||||
mCustomTitle = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(int titleId) {
|
||||
setTitle(getContext().getString(titleId));
|
||||
}
|
||||
|
||||
/** Called after flags are set, the dialog's layout/etc should be set up here */
|
||||
private void onLayout() {
|
||||
final Context context = getContext();
|
||||
final String ssid = mState.getHumanReadableSsid();
|
||||
|
||||
int positiveButtonResId = 0;
|
||||
int negativeButtonResId = R.string.cancel;
|
||||
int neutralButtonResId = 0;
|
||||
|
||||
if (mCustomTitle == null) {
|
||||
// Generic title is the SSID
|
||||
// We don't want to trigger this as a custom title, so call super's
|
||||
super.setTitle(ssid);
|
||||
}
|
||||
setInverseBackgroundForced(true);
|
||||
|
||||
boolean defaultPasswordVisibility = true;
|
||||
|
||||
if (mMode == MODE_CONFIGURE) {
|
||||
setLayout(R.layout.wifi_ap_configure);
|
||||
|
||||
positiveButtonResId = R.string.wifi_save_config;
|
||||
mSaveButtonPos = POSITIVE_BUTTON;
|
||||
|
||||
} else if (mMode == MODE_INFO) {
|
||||
setLayout(R.layout.wifi_ap_info);
|
||||
|
||||
if (mState.isConnectable()) {
|
||||
if (mCustomTitle == null) {
|
||||
// We don't want to trigger this as a custom title, so call super's
|
||||
super.setTitle(context.getString(R.string.connect_to_blank, ssid));
|
||||
}
|
||||
positiveButtonResId = R.string.connect;
|
||||
mConnectButtonPos = POSITIVE_BUTTON;
|
||||
}
|
||||
|
||||
if (mState.isForgetable()) {
|
||||
if (positiveButtonResId == 0) {
|
||||
positiveButtonResId = R.string.forget_network;
|
||||
mForgetButtonPos = POSITIVE_BUTTON;
|
||||
} else {
|
||||
neutralButtonResId = R.string.forget_network;
|
||||
mForgetButtonPos = NEUTRAL_BUTTON;
|
||||
}
|
||||
}
|
||||
} else if (mMode == MODE_RETRY_PASSWORD) {
|
||||
setLayout(R.layout.wifi_ap_retry_password);
|
||||
|
||||
positiveButtonResId = R.string.connect;
|
||||
mConnectButtonPos = POSITIVE_BUTTON;
|
||||
|
||||
setGenericPasswordVisible(true);
|
||||
defaultPasswordVisibility = false;
|
||||
}
|
||||
|
||||
if (defaultPasswordVisibility) {
|
||||
if (!mState.configured && mState.seen && mState.hasSecurity()) {
|
||||
setGenericPasswordVisible(true);
|
||||
} else {
|
||||
setGenericPasswordVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
setButtons(positiveButtonResId, negativeButtonResId, neutralButtonResId);
|
||||
}
|
||||
|
||||
/** Called when we need to set our member variables to point to the views. */
|
||||
private void onReferenceViews(View view) {
|
||||
mPasswordText = (TextView) view.findViewById(R.id.password_text);
|
||||
mPasswordEdit = (EditText) view.findViewById(R.id.password_edit);
|
||||
|
||||
mShowPasswordCheckBox = (CheckBox) view.findViewById(R.id.show_password_checkbox);
|
||||
if (mShowPasswordCheckBox != null) {
|
||||
mShowPasswordCheckBox.setOnClickListener(this);
|
||||
}
|
||||
|
||||
if (mMode == MODE_CONFIGURE) {
|
||||
mSsidEdit = (EditText) view.findViewById(R.id.ssid_edit);
|
||||
mSecuritySpinner = (Spinner) view.findViewById(R.id.security_spinner);
|
||||
mSecuritySpinner.setOnItemSelectedListener(this);
|
||||
setSecuritySpinnerAdapter();
|
||||
mWepTypeSpinner = (Spinner) view.findViewById(R.id.wep_type_spinner);
|
||||
|
||||
} else if (mMode == MODE_INFO) {
|
||||
mTable = (ViewGroup) view.findViewById(R.id.table);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void setSecuritySpinnerAdapter() {
|
||||
Context context = getContext();
|
||||
int arrayResId = mAutoSecurityAllowed ? R.array.wifi_security_entries
|
||||
: R.array.wifi_security_without_auto_entries;
|
||||
|
||||
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(context,
|
||||
android.R.layout.simple_spinner_item,
|
||||
context.getResources().getStringArray(arrayResId));
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
mSecuritySpinner.setAdapter(adapter);
|
||||
}
|
||||
|
||||
/** Called when the widgets are in-place waiting to be filled with data */
|
||||
private void onFill() {
|
||||
|
||||
// Appears in the order added
|
||||
if (mMode == MODE_INFO) {
|
||||
if (mState.primary) {
|
||||
addInfoRow(R.string.wifi_status, mState.getSummarizedStatus());
|
||||
addInfoRow(R.string.wifi_link_speed, mState.linkSpeed + WifiInfo.LINK_SPEED_UNITS);
|
||||
}
|
||||
|
||||
if (mState.seen) {
|
||||
addInfoRow(R.string.signal, getSignalResId(mState.signal));
|
||||
}
|
||||
|
||||
if (mState.security != null) {
|
||||
addInfoRow(R.string.security, mState.getHumanReadableSecurity());
|
||||
}
|
||||
|
||||
if (mState.primary && mState.ipAddress != 0) {
|
||||
addInfoRow(R.string.ip_address, ipAddressToString(mState.ipAddress));
|
||||
}
|
||||
|
||||
} else if (mMode == MODE_CONFIGURE) {
|
||||
String ssid = mState.getHumanReadableSsid();
|
||||
if (!TextUtils.isEmpty(ssid)) {
|
||||
mSsidEdit.setText(ssid);
|
||||
}
|
||||
|
||||
mPasswordEdit.setHint(R.string.wifi_password_unchanged);
|
||||
}
|
||||
|
||||
updatePasswordCaption(mState.security);
|
||||
}
|
||||
|
||||
private void updatePasswordCaption(String security) {
|
||||
|
||||
if (mPasswordText != null && security != null
|
||||
&& security.equals(AccessPointState.WEP)) {
|
||||
mPasswordText.setText(R.string.please_type_hex_key);
|
||||
} else {
|
||||
mPasswordText.setText(R.string.please_type_passphrase);
|
||||
}
|
||||
}
|
||||
|
||||
private void addInfoRow(int nameResId, String value) {
|
||||
View rowView = getLayoutInflater().inflate(R.layout.wifi_ap_info_row, mTable, false);
|
||||
((TextView) rowView.findViewById(R.id.name)).setText(nameResId);
|
||||
((TextView) rowView.findViewById(R.id.value)).setText(value);
|
||||
mTable.addView(rowView);
|
||||
}
|
||||
|
||||
private void addInfoRow(int nameResId, int valueResId) {
|
||||
addInfoRow(nameResId, getContext().getString(valueResId));
|
||||
}
|
||||
|
||||
private void setButtons(int positiveResId, int negativeResId, int neutralResId) {
|
||||
final Context context = getContext();
|
||||
|
||||
if (positiveResId > 0) {
|
||||
setButton(context.getString(positiveResId), this);
|
||||
}
|
||||
|
||||
if (negativeResId > 0) {
|
||||
setButton2(context.getString(negativeResId), this);
|
||||
}
|
||||
|
||||
if (neutralResId > 0) {
|
||||
setButton3(context.getString(neutralResId), this);
|
||||
}
|
||||
}
|
||||
|
||||
private void setLayout(int layoutResId) {
|
||||
setView(mView = getLayoutInflater().inflate(layoutResId, null));
|
||||
onReferenceViews(mView);
|
||||
}
|
||||
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (which == mForgetButtonPos) {
|
||||
handleForget();
|
||||
} else if (which == mConnectButtonPos) {
|
||||
handleConnect();
|
||||
} else if (which == mSaveButtonPos) {
|
||||
handleSave();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleForget() {
|
||||
if (!replaceStateWithWifiLayerInstance()) return;
|
||||
mWifiLayer.forgetNetwork(mState);
|
||||
}
|
||||
|
||||
private void handleConnect() {
|
||||
if (!replaceStateWithWifiLayerInstance()) {
|
||||
Log.w(TAG, "Assuming connecting to a new network.");
|
||||
}
|
||||
|
||||
/*
|
||||
* If the network is secured and they haven't entered a password, popup
|
||||
* an error. Allow empty passwords if the state already has a password
|
||||
* set (since in that scenario, an empty password means keep the old
|
||||
* password).
|
||||
*/
|
||||
String password = getEnteredPassword();
|
||||
boolean passwordIsEmpty = TextUtils.isEmpty(password);
|
||||
|
||||
/*
|
||||
* When 'retry password', they can not enter a blank password. In any
|
||||
* other mode, we let them enter a blank password if the state already
|
||||
* has a password.
|
||||
*/
|
||||
if (passwordIsEmpty && (!mState.hasPassword() || mMode == MODE_RETRY_PASSWORD)
|
||||
&& (mState.security != null) && !mState.security.equals(AccessPointState.OPEN)) {
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setTitle(R.string.error_title)
|
||||
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||
.setMessage(R.string.wifi_password_incorrect_error)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!passwordIsEmpty) {
|
||||
mState.setPassword(password);
|
||||
}
|
||||
|
||||
mWifiLayer.connectToNetwork(mState);
|
||||
}
|
||||
|
||||
private void handleSave() {
|
||||
replaceStateWithWifiLayerInstance();
|
||||
|
||||
String ssid = mSsidEdit.getText().toString();
|
||||
String password = mPasswordEdit.getText().toString();
|
||||
|
||||
mState.setSsid(ssid);
|
||||
|
||||
int securityType = getSecurityTypeFromSpinner();
|
||||
|
||||
if (!TextUtils.isEmpty(password)) {
|
||||
switch (securityType) {
|
||||
|
||||
case SECURITY_WPA_PERSONAL: {
|
||||
mState.setSecurity(AccessPointState.WPA);
|
||||
mState.setPassword(password);
|
||||
break;
|
||||
}
|
||||
|
||||
case SECURITY_WPA2_PERSONAL: {
|
||||
mState.setSecurity(AccessPointState.WPA2);
|
||||
mState.setPassword(password);
|
||||
break;
|
||||
}
|
||||
|
||||
case SECURITY_AUTO: {
|
||||
mState.setPassword(password);
|
||||
break;
|
||||
}
|
||||
|
||||
case SECURITY_WEP: {
|
||||
mState.setSecurity(AccessPointState.WEP);
|
||||
mState.setPassword(password,
|
||||
WEP_TYPE_VALUES[mWepTypeSpinner.getSelectedItemPosition()]);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
mState.setSecurity(AccessPointState.OPEN);
|
||||
}
|
||||
|
||||
if (securityType == SECURITY_NONE) {
|
||||
mState.setSecurity(AccessPointState.OPEN);
|
||||
}
|
||||
|
||||
if (!mWifiLayer.saveNetwork(mState)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Connect right away if they've touched it
|
||||
if (!mWifiLayer.connectToNetwork(mState)) {
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces our {@link #mState} with the equal WifiLayer instance. This is useful after
|
||||
* we unparceled the state previously and before we are calling methods on {@link #mWifiLayer}.
|
||||
*
|
||||
* @return Whether WifiLayer was able to find an equal state in its set.
|
||||
*/
|
||||
private boolean replaceStateWithWifiLayerInstance() {
|
||||
AccessPointState state = mWifiLayer.getWifiLayerApInstance(mState);
|
||||
if (state == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mState = state;
|
||||
return true;
|
||||
}
|
||||
|
||||
private int getSecurityTypeFromSpinner() {
|
||||
int position = mSecuritySpinner.getSelectedItemPosition();
|
||||
// If there is no AUTO choice, the position needs 1 added to get
|
||||
// to the proper spinner position -> security constants mapping
|
||||
return mAutoSecurityAllowed ? position : position + 1;
|
||||
}
|
||||
|
||||
private String getEnteredPassword() {
|
||||
return mPasswordEdit != null ? mPasswordEdit.getText().toString() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the one you want to hide first.
|
||||
*/
|
||||
private void setWepVisible(boolean visible) {
|
||||
setGenericPasswordVisible(visible);
|
||||
int visibility = visible ? View.VISIBLE : View.GONE;
|
||||
mWepTypeSpinner.setVisibility(visibility);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #setWepVisible(boolean)
|
||||
*/
|
||||
private void setGenericPasswordVisible(boolean visible) {
|
||||
int visibility = visible ? View.VISIBLE : View.GONE;
|
||||
mPasswordText.setVisibility(visibility);
|
||||
mPasswordEdit.setVisibility(visibility);
|
||||
mShowPasswordCheckBox.setVisibility(visibility);
|
||||
}
|
||||
|
||||
public void onItemSelected(AdapterView parent, View view, int position, long id) {
|
||||
if (parent == mSecuritySpinner) {
|
||||
handleSecurityChange(getSecurityTypeFromSpinner());
|
||||
}
|
||||
}
|
||||
|
||||
public void onNothingSelected(AdapterView parent) {
|
||||
}
|
||||
|
||||
private void handleSecurityChange(int security) {
|
||||
|
||||
switch (security) {
|
||||
|
||||
case SECURITY_NONE: {
|
||||
setWepVisible(false);
|
||||
setGenericPasswordVisible(false);
|
||||
break;
|
||||
}
|
||||
|
||||
case SECURITY_WEP: {
|
||||
setGenericPasswordVisible(false);
|
||||
setWepVisible(true);
|
||||
updatePasswordCaption(AccessPointState.WEP);
|
||||
break;
|
||||
}
|
||||
|
||||
case SECURITY_AUTO: {
|
||||
setWepVisible(false);
|
||||
setGenericPasswordVisible(mState.hasSecurity());
|
||||
// Shows the generic 'wireless password'
|
||||
updatePasswordCaption(AccessPointState.WPA);
|
||||
break;
|
||||
}
|
||||
|
||||
case SECURITY_WPA_PERSONAL:
|
||||
case SECURITY_WPA2_PERSONAL: {
|
||||
setWepVisible(false);
|
||||
setGenericPasswordVisible(true);
|
||||
// Both WPA and WPA2 show the same caption, so either is ok
|
||||
updatePasswordCaption(AccessPointState.WPA);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int getSignalResId(int signal) {
|
||||
switch (WifiManager.calculateSignalLevel(signal, 4)) {
|
||||
case 0: {
|
||||
return R.string.wifi_signal_0;
|
||||
}
|
||||
case 1: {
|
||||
return R.string.wifi_signal_1;
|
||||
}
|
||||
case 2: {
|
||||
return R.string.wifi_signal_2;
|
||||
}
|
||||
case 3: {
|
||||
return R.string.wifi_signal_3;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static String ipAddressToString(int addr) {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(addr & 0xff).append('.').
|
||||
append((addr >>>= 8) & 0xff).append('.').
|
||||
append((addr >>>= 8) & 0xff).append('.').
|
||||
append((addr >>>= 8) & 0xff);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public void onClick(View v) {
|
||||
if (v == mShowPasswordCheckBox) {
|
||||
setShowPassword(mShowPasswordCheckBox.isChecked());
|
||||
}
|
||||
}
|
||||
|
||||
private void setShowPassword(boolean showPassword) {
|
||||
if (mPasswordEdit != null) {
|
||||
// Toggle password
|
||||
mPasswordEdit.setTransformationMethod(
|
||||
showPassword ?
|
||||
null :
|
||||
PasswordTransformationMethod.getInstance());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
108
src/com/android/settings/wifi/AccessPointPreference.java
Normal file
108
src/com/android/settings/wifi/AccessPointPreference.java
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.preference.Preference;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
public class AccessPointPreference extends Preference implements
|
||||
AccessPointState.AccessPointStateCallback {
|
||||
|
||||
// UI states
|
||||
private static final int[] STATE_ENCRYPTED = { R.attr.state_encrypted };
|
||||
private static final int[] STATE_EMPTY = { };
|
||||
|
||||
// Signal strength indicator
|
||||
private static final int UI_SIGNAL_LEVELS = 4;
|
||||
|
||||
private WifiSettings mWifiSettings;
|
||||
|
||||
private AccessPointState mState;
|
||||
|
||||
public AccessPointPreference(WifiSettings wifiSettings, AccessPointState state) {
|
||||
super(wifiSettings, null);
|
||||
|
||||
mWifiSettings = wifiSettings;
|
||||
mState = state;
|
||||
|
||||
setWidgetLayoutResource(R.layout.preference_widget_wifi_signal);
|
||||
|
||||
state.setCallback(this);
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
setTitle(mState.getHumanReadableSsid());
|
||||
setSummary(mState.getSummarizedStatus());
|
||||
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
public void refreshAccessPointState() {
|
||||
refresh();
|
||||
|
||||
// The ordering of access points could have changed due to the state change, so
|
||||
// re-evaluate ordering
|
||||
notifyHierarchyChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindView(View view) {
|
||||
super.onBindView(view);
|
||||
|
||||
ImageView signal = (ImageView) view.findViewById(R.id.signal);
|
||||
if (mState.seen) {
|
||||
signal.setImageResource(R.drawable.wifi_signal);
|
||||
signal.setImageState(mState.hasSecurity() ? STATE_ENCRYPTED : STATE_EMPTY, true);
|
||||
signal.setImageLevel(getUiSignalLevel());
|
||||
} else {
|
||||
signal.setImageDrawable(null);
|
||||
}
|
||||
}
|
||||
|
||||
private int getUiSignalLevel() {
|
||||
return mState != null ? WifiManager.calculateSignalLevel(mState.signal, UI_SIGNAL_LEVELS)
|
||||
: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link AccessPointState} associated with this preference.
|
||||
* @return The {@link AccessPointState}.
|
||||
*/
|
||||
public AccessPointState getAccessPointState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Preference another) {
|
||||
if (!(another instanceof AccessPointPreference)) {
|
||||
// Let normal preferences go before us.
|
||||
// NOTE: we should only be compared to Preference in our
|
||||
// category.
|
||||
return 1;
|
||||
}
|
||||
|
||||
return mState.compareTo(((AccessPointPreference) another).mState);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
869
src/com/android/settings/wifi/AccessPointState.java
Normal file
869
src/com/android/settings/wifi/AccessPointState.java
Normal file
@@ -0,0 +1,869 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.wifi.ScanResult;
|
||||
import android.net.wifi.WifiConfiguration;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
|
||||
import android.net.wifi.WifiConfiguration.GroupCipher;
|
||||
import android.net.wifi.WifiConfiguration.KeyMgmt;
|
||||
import android.net.wifi.WifiConfiguration.PairwiseCipher;
|
||||
import android.net.wifi.WifiConfiguration.Protocol;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
public final class AccessPointState implements Comparable<AccessPointState>, Parcelable {
|
||||
|
||||
private static final String TAG = "AccessPointState";
|
||||
|
||||
// Constants used for different security types
|
||||
public static final String WPA2 = "WPA2";
|
||||
public static final String WPA = "WPA";
|
||||
public static final String WEP = "WEP";
|
||||
public static final String OPEN = "Open";
|
||||
|
||||
/** String present in capabilities if the scan result is ad-hoc */
|
||||
private static final String ADHOC_CAPABILITY = "[IBSS]";
|
||||
/** String present in capabilities if the scan result is enterprise secured */
|
||||
private static final String ENTERPRISE_CAPABILITY = "-EAP-";
|
||||
|
||||
// Localized strings for different security types
|
||||
private static String LOCALIZED_WPA2;
|
||||
private static String LOCALIZED_WPA;
|
||||
private static String LOCALIZED_WEP;
|
||||
private static String LOCALIZED_OPEN;
|
||||
private static String LOCALIZED_UNKNOWN;
|
||||
private static String LOCALIZED_VERBOSE_WPA2;
|
||||
private static String LOCALIZED_VERBOSE_WPA;
|
||||
private static String LOCALIZED_VERBOSE_WEP;
|
||||
private static String LOCALIZED_VERBOSE_OPEN;
|
||||
|
||||
|
||||
// Localized strings for various messages
|
||||
private static String SUMMARY_NOT_IN_RANGE;
|
||||
private static String SUMMARY_REMEMBERED;
|
||||
private static String SUMMARY_CONNECTION_FAILED;
|
||||
|
||||
public static final String BSSID_ANY = "any";
|
||||
public static final int NETWORK_ID_NOT_SET = -1;
|
||||
/** This should be used with care! */
|
||||
static final int NETWORK_ID_ANY = -2;
|
||||
|
||||
public static final int MATCH_NONE = 0;
|
||||
public static final int MATCH_WEAK = 1;
|
||||
public static final int MATCH_STRONG = 2;
|
||||
public static final int MATCH_EXACT = 3;
|
||||
|
||||
// Don't set these directly, use the setters.
|
||||
public int networkId;
|
||||
public int priority;
|
||||
public boolean hiddenSsid;
|
||||
public int linkSpeed;
|
||||
public int ipAddress;
|
||||
public String bssid;
|
||||
public String ssid;
|
||||
public int signal;
|
||||
public boolean primary;
|
||||
public boolean seen;
|
||||
public boolean configured;
|
||||
public NetworkInfo.DetailedState status;
|
||||
public String security;
|
||||
public boolean disabled;
|
||||
|
||||
/**
|
||||
* Use this for sorting based on signal strength. It is a heavily-damped
|
||||
* time-averaged weighted signal.
|
||||
*/
|
||||
private float signalForSorting = Float.MIN_VALUE;
|
||||
|
||||
private static final float DAMPING_FACTOR = 0.2f;
|
||||
|
||||
/**
|
||||
* This will be a user entered password, and NOT taken from wpa_supplicant
|
||||
* (since it would give us *)
|
||||
*/
|
||||
private String mPassword;
|
||||
private boolean mConfigHadPassword;
|
||||
|
||||
public static final int WEP_PASSWORD_AUTO = 0;
|
||||
public static final int WEP_PASSWORD_ASCII = 1;
|
||||
public static final int WEP_PASSWORD_HEX = 2;
|
||||
private int mWepPasswordType;
|
||||
|
||||
private Context mContext;
|
||||
|
||||
/**
|
||||
* If > 0, don't refresh (changes are being batched), use
|
||||
* {@link #blockRefresh()} and {@link #unblockRefresh()} only.
|
||||
*/
|
||||
private int mBlockRefresh;
|
||||
/**
|
||||
* This will be set by {@link #requestRefresh} and shouldn't be written to
|
||||
* elsewhere.
|
||||
*/
|
||||
private boolean mNeedsRefresh;
|
||||
|
||||
private AccessPointStateCallback mCallback;
|
||||
|
||||
private StringBuilder mSummaryBuilder = new StringBuilder();
|
||||
|
||||
interface AccessPointStateCallback {
|
||||
void refreshAccessPointState();
|
||||
}
|
||||
|
||||
public AccessPointState(Context context) {
|
||||
this();
|
||||
|
||||
setContext(context);
|
||||
}
|
||||
|
||||
private AccessPointState() {
|
||||
bssid = BSSID_ANY;
|
||||
ssid = "";
|
||||
networkId = NETWORK_ID_NOT_SET;
|
||||
hiddenSsid = false;
|
||||
}
|
||||
|
||||
void setContext(Context context) {
|
||||
mContext = context;
|
||||
setStrings();
|
||||
}
|
||||
|
||||
private void setStrings() {
|
||||
final Context c = mContext;
|
||||
|
||||
if (SUMMARY_NOT_IN_RANGE == null && c != null) {
|
||||
SUMMARY_NOT_IN_RANGE = c.getString(R.string.summary_not_in_range);
|
||||
SUMMARY_REMEMBERED = c.getString(R.string.summary_remembered);
|
||||
SUMMARY_CONNECTION_FAILED = c.getString(R.string.summary_connection_failed);
|
||||
|
||||
LOCALIZED_OPEN = c.getString(R.string.wifi_security_open);
|
||||
LOCALIZED_WEP = c.getString(R.string.wifi_security_wep);
|
||||
LOCALIZED_WPA = c.getString(R.string.wifi_security_wpa);
|
||||
LOCALIZED_WPA2 = c.getString(R.string.wifi_security_wpa2);
|
||||
|
||||
LOCALIZED_VERBOSE_OPEN = c.getString(R.string.wifi_security_verbose_open);
|
||||
LOCALIZED_VERBOSE_WEP = c.getString(R.string.wifi_security_verbose_wep);
|
||||
LOCALIZED_VERBOSE_WPA = c.getString(R.string.wifi_security_verbose_wpa);
|
||||
LOCALIZED_VERBOSE_WPA2 = c.getString(R.string.wifi_security_verbose_wpa2);
|
||||
|
||||
LOCALIZED_UNKNOWN = c.getString(R.string.wifi_security_unknown);
|
||||
}
|
||||
}
|
||||
|
||||
public void setNetworkId(int networkId) {
|
||||
this.networkId = networkId;
|
||||
}
|
||||
|
||||
public void setBssid(String bssid) {
|
||||
if (bssid != null) {
|
||||
// If the BSSID is a wildcard, do NOT let a specific BSSID replace it
|
||||
if (!this.bssid.equals(BSSID_ANY)) {
|
||||
this.bssid = bssid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getWpaSupplicantBssid() {
|
||||
return bssid.equals(BSSID_ANY) ? null : bssid;
|
||||
}
|
||||
|
||||
public static String convertToQuotedString(String string) {
|
||||
if (TextUtils.isEmpty(string)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
final int lastPos = string.length() - 1;
|
||||
if (lastPos < 0 || (string.charAt(0) == '"' && string.charAt(lastPos) == '"')) {
|
||||
return string;
|
||||
}
|
||||
|
||||
return "\"" + string + "\"";
|
||||
}
|
||||
|
||||
public void setPrimary(boolean primary) {
|
||||
if (this.primary != primary) {
|
||||
this.primary = primary;
|
||||
requestRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void setSeen(boolean seen) {
|
||||
if (this.seen != seen) {
|
||||
this.seen = seen;
|
||||
requestRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void setDisabled(boolean disabled) {
|
||||
if (this.disabled != disabled) {
|
||||
this.disabled = disabled;
|
||||
requestRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void setSignal(int signal) {
|
||||
|
||||
if (signalForSorting == Float.MIN_VALUE) {
|
||||
signalForSorting = signal;
|
||||
} else {
|
||||
signalForSorting = (DAMPING_FACTOR * signal) + ((1-DAMPING_FACTOR) * signalForSorting);
|
||||
}
|
||||
|
||||
if (this.signal != signal) {
|
||||
this.signal = signal;
|
||||
requestRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public String getHumanReadableSsid() {
|
||||
if (TextUtils.isEmpty(ssid)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
final int lastPos = ssid.length() - 1;
|
||||
if (ssid.charAt(0) == '"' && ssid.charAt(lastPos) == '"') {
|
||||
return ssid.substring(1, lastPos);
|
||||
}
|
||||
|
||||
return ssid;
|
||||
}
|
||||
|
||||
public void setSsid(String ssid) {
|
||||
if (ssid != null) {
|
||||
this.ssid = convertToQuotedString(ssid);
|
||||
requestRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void setPriority(int priority) {
|
||||
if (this.priority != priority) {
|
||||
this.priority = priority;
|
||||
requestRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void setHiddenSsid(boolean hiddenSsid) {
|
||||
if (this.hiddenSsid != hiddenSsid) {
|
||||
this.hiddenSsid = hiddenSsid;
|
||||
requestRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void setLinkSpeed(int linkSpeed) {
|
||||
if (this.linkSpeed != linkSpeed) {
|
||||
this.linkSpeed = linkSpeed;
|
||||
requestRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void setIpAddress(int address) {
|
||||
if (ipAddress != address) {
|
||||
ipAddress = address;
|
||||
requestRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void setConfigured(boolean configured) {
|
||||
if (this.configured != configured) {
|
||||
this.configured = configured;
|
||||
requestRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void setStatus(NetworkInfo.DetailedState status) {
|
||||
if (this.status != status) {
|
||||
this.status = status;
|
||||
requestRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void setSecurity(String security) {
|
||||
if (TextUtils.isEmpty(this.security) || !this.security.equals(security)) {
|
||||
this.security = security;
|
||||
requestRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasSecurity() {
|
||||
return security != null && !security.contains(OPEN);
|
||||
}
|
||||
|
||||
public String getHumanReadableSecurity() {
|
||||
if (security.equals(OPEN)) return LOCALIZED_OPEN;
|
||||
else if (security.equals(WEP)) return LOCALIZED_WEP;
|
||||
else if (security.equals(WPA)) return LOCALIZED_WPA;
|
||||
else if (security.equals(WPA2)) return LOCALIZED_WPA2;
|
||||
|
||||
return LOCALIZED_UNKNOWN;
|
||||
}
|
||||
|
||||
public void updateFromScanResult(ScanResult scanResult) {
|
||||
blockRefresh();
|
||||
|
||||
// We don't keep specific AP BSSIDs and instead leave that as wildcard
|
||||
|
||||
setSeen(true);
|
||||
setSsid(scanResult.SSID);
|
||||
if (networkId == NETWORK_ID_NOT_SET) {
|
||||
// Since ScanResults don't cross-reference network ID, we set it as a wildcard
|
||||
setNetworkId(NETWORK_ID_ANY);
|
||||
}
|
||||
setSignal(scanResult.level);
|
||||
setSecurity(getScanResultSecurity(scanResult));
|
||||
unblockRefresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The security of a given {@link ScanResult}.
|
||||
*/
|
||||
public static String getScanResultSecurity(ScanResult scanResult) {
|
||||
final String cap = scanResult.capabilities;
|
||||
final String[] securityModes = { WEP, WPA, WPA2 };
|
||||
for (int i = securityModes.length - 1; i >= 0; i--) {
|
||||
if (cap.contains(securityModes[i])) {
|
||||
return securityModes[i];
|
||||
}
|
||||
}
|
||||
|
||||
return OPEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether the given ScanResult represents an adhoc network.
|
||||
*/
|
||||
public static boolean isAdhoc(ScanResult scanResult) {
|
||||
return scanResult.capabilities.contains(ADHOC_CAPABILITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether the given ScanResult has enterprise security.
|
||||
*/
|
||||
public static boolean isEnterprise(ScanResult scanResult) {
|
||||
return scanResult.capabilities.contains(ENTERPRISE_CAPABILITY);
|
||||
}
|
||||
|
||||
public void updateFromWifiConfiguration(WifiConfiguration wifiConfig) {
|
||||
if (wifiConfig != null) {
|
||||
blockRefresh();
|
||||
setBssid(wifiConfig.BSSID);
|
||||
setNetworkId(wifiConfig.networkId);
|
||||
setPriority(wifiConfig.priority);
|
||||
setHiddenSsid(wifiConfig.hiddenSSID);
|
||||
setSsid(wifiConfig.SSID);
|
||||
setConfigured(true);
|
||||
setDisabled(wifiConfig.status == WifiConfiguration.Status.DISABLED);
|
||||
parseWifiConfigurationSecurity(wifiConfig);
|
||||
unblockRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
setPassword(password, WEP_PASSWORD_AUTO);
|
||||
}
|
||||
|
||||
public void setPassword(String password, int wepPasswordType) {
|
||||
mPassword = password;
|
||||
mWepPasswordType = wepPasswordType;
|
||||
}
|
||||
|
||||
public boolean hasPassword() {
|
||||
return !TextUtils.isEmpty(mPassword) || mConfigHadPassword;
|
||||
}
|
||||
|
||||
private static boolean hasPassword(WifiConfiguration wifiConfig) {
|
||||
return !TextUtils.isEmpty(wifiConfig.preSharedKey)
|
||||
|| !TextUtils.isEmpty(wifiConfig.wepKeys[0])
|
||||
|| !TextUtils.isEmpty(wifiConfig.wepKeys[1])
|
||||
|| !TextUtils.isEmpty(wifiConfig.wepKeys[2])
|
||||
|| !TextUtils.isEmpty(wifiConfig.wepKeys[3]);
|
||||
}
|
||||
|
||||
private void parseWifiConfigurationSecurity(WifiConfiguration wifiConfig) {
|
||||
setSecurity(getWifiConfigurationSecurity(wifiConfig));
|
||||
mConfigHadPassword = hasPassword(wifiConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The security of a given {@link WifiConfiguration}.
|
||||
*/
|
||||
public static String getWifiConfigurationSecurity(WifiConfiguration wifiConfig) {
|
||||
|
||||
if (wifiConfig.allowedKeyManagement.get(KeyMgmt.NONE)) {
|
||||
// If we never set group ciphers, wpa_supplicant puts all of them.
|
||||
// For open, we don't set group ciphers.
|
||||
// For WEP, we specifically only set WEP40 and WEP104, so CCMP
|
||||
// and TKIP should not be there.
|
||||
if (!wifiConfig.allowedGroupCiphers.get(GroupCipher.CCMP)
|
||||
&& (wifiConfig.allowedGroupCiphers.get(GroupCipher.WEP40)
|
||||
|| wifiConfig.allowedGroupCiphers.get(GroupCipher.WEP104))) {
|
||||
return WEP;
|
||||
} else {
|
||||
return OPEN;
|
||||
}
|
||||
} else if (wifiConfig.allowedProtocols.get(Protocol.RSN)) {
|
||||
return WPA2;
|
||||
} else if (wifiConfig.allowedProtocols.get(Protocol.WPA)) {
|
||||
return WPA;
|
||||
} else {
|
||||
Log.w(TAG, "Unknown security type from WifiConfiguration, falling back on open.");
|
||||
return OPEN;
|
||||
}
|
||||
}
|
||||
|
||||
public void updateFromWifiInfo(WifiInfo wifiInfo, NetworkInfo.DetailedState state) {
|
||||
if (wifiInfo != null) {
|
||||
blockRefresh();
|
||||
setBssid(wifiInfo.getBSSID());
|
||||
setLinkSpeed(wifiInfo.getLinkSpeed());
|
||||
setNetworkId(wifiInfo.getNetworkId());
|
||||
setIpAddress(wifiInfo.getIpAddress());
|
||||
setSsid(wifiInfo.getSSID());
|
||||
if (state != null) {
|
||||
setStatus(state);
|
||||
}
|
||||
setHiddenSsid(wifiInfo.getHiddenSSID());
|
||||
unblockRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether this AP can be connected to at the moment.
|
||||
*/
|
||||
public boolean isConnectable() {
|
||||
return !primary && seen;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether this AP can be forgotten at the moment.
|
||||
*/
|
||||
public boolean isForgetable() {
|
||||
return configured;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the state as if it were never configured.
|
||||
* <p>
|
||||
* Note: This will not pass the forget call to the Wi-Fi API.
|
||||
*/
|
||||
public void forget() {
|
||||
blockRefresh();
|
||||
setConfigured(false);
|
||||
setNetworkId(NETWORK_ID_NOT_SET);
|
||||
setPrimary(false);
|
||||
setStatus(null);
|
||||
setDisabled(false);
|
||||
unblockRefresh();
|
||||
}
|
||||
|
||||
public void updateWifiConfiguration(WifiConfiguration config) {
|
||||
config.BSSID = getWpaSupplicantBssid();
|
||||
config.priority = priority;
|
||||
config.hiddenSSID = hiddenSsid;
|
||||
config.SSID = convertToQuotedString(ssid);
|
||||
|
||||
setupSecurity(config);
|
||||
}
|
||||
|
||||
private void setupSecurity(WifiConfiguration config) {
|
||||
config.allowedAuthAlgorithms.clear();
|
||||
config.allowedGroupCiphers.clear();
|
||||
config.allowedKeyManagement.clear();
|
||||
config.allowedPairwiseCiphers.clear();
|
||||
config.allowedProtocols.clear();
|
||||
|
||||
if (TextUtils.isEmpty(security)) {
|
||||
security = OPEN;
|
||||
Log.w(TAG, "Empty security, assuming open");
|
||||
}
|
||||
|
||||
if (security.equals(WEP)) {
|
||||
|
||||
// If password is empty, it should be left untouched
|
||||
if (!TextUtils.isEmpty(mPassword)) {
|
||||
if (mWepPasswordType == WEP_PASSWORD_AUTO) {
|
||||
if (isHexWepKey(mPassword)) {
|
||||
config.wepKeys[0] = mPassword;
|
||||
} else {
|
||||
config.wepKeys[0] = convertToQuotedString(mPassword);
|
||||
}
|
||||
} else {
|
||||
config.wepKeys[0] = mWepPasswordType == WEP_PASSWORD_ASCII
|
||||
? convertToQuotedString(mPassword)
|
||||
: mPassword;
|
||||
}
|
||||
}
|
||||
|
||||
config.wepTxKeyIndex = 0;
|
||||
|
||||
config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
|
||||
config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
|
||||
|
||||
config.allowedKeyManagement.set(KeyMgmt.NONE);
|
||||
|
||||
config.allowedGroupCiphers.set(GroupCipher.WEP40);
|
||||
config.allowedGroupCiphers.set(GroupCipher.WEP104);
|
||||
|
||||
} else if (security.equals(WPA) || security.equals(WPA2)){
|
||||
config.allowedGroupCiphers.set(GroupCipher.TKIP);
|
||||
config.allowedGroupCiphers.set(GroupCipher.CCMP);
|
||||
|
||||
config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
|
||||
|
||||
config.allowedPairwiseCiphers.set(PairwiseCipher.CCMP);
|
||||
config.allowedPairwiseCiphers.set(PairwiseCipher.TKIP);
|
||||
|
||||
config.allowedProtocols.set(security.equals(WPA2) ? Protocol.RSN : Protocol.WPA);
|
||||
|
||||
// If password is empty, it should be left untouched
|
||||
if (!TextUtils.isEmpty(mPassword)) {
|
||||
config.preSharedKey = convertToQuotedString(mPassword);
|
||||
}
|
||||
|
||||
} else if (security.equals(OPEN)) {
|
||||
config.allowedKeyManagement.set(KeyMgmt.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isHexWepKey(String wepKey) {
|
||||
final int len = wepKey.length();
|
||||
|
||||
// WEP-40, WEP-104, and some vendors using 256-bit WEP (WEP-232?)
|
||||
if (len != 10 && len != 26 && len != 58) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = len - 1; i >= 0; i--) {
|
||||
final char c = wepKey.charAt(i);
|
||||
if (!(c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setCallback(AccessPointStateCallback callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
void blockRefresh() {
|
||||
mBlockRefresh++;
|
||||
}
|
||||
|
||||
void unblockRefresh() {
|
||||
if (--mBlockRefresh == 0 && mNeedsRefresh) {
|
||||
requestRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
private void requestRefresh() {
|
||||
if (mBlockRefresh > 0) {
|
||||
mNeedsRefresh = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCallback != null) {
|
||||
mCallback.refreshAccessPointState();
|
||||
}
|
||||
|
||||
mNeedsRefresh = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see #hashCode()
|
||||
* @see #equals(Object)
|
||||
*/
|
||||
public int matches(int otherNetworkId, String otherBssid, String otherSsid,
|
||||
String otherSecurity) {
|
||||
|
||||
// Whenever this method is touched, please ensure #equals and #hashCode
|
||||
// still work with the changes here!
|
||||
|
||||
if (otherSsid == null) {
|
||||
if (WifiLayer.LOGV) {
|
||||
Log.w(TAG, "BSSID: " + otherBssid + ", SSID: " + otherSsid);
|
||||
}
|
||||
return MATCH_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we both have 'security' set, it must match (an open network still
|
||||
* has 'security' set to OPEN)
|
||||
*/
|
||||
if (security != null && otherSecurity != null) {
|
||||
if (!security.equals(otherSecurity)) {
|
||||
return MATCH_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
// WifiConfiguration gives an empty bssid as a BSSID wildcard
|
||||
if (TextUtils.isEmpty(otherBssid)) {
|
||||
otherBssid = AccessPointState.BSSID_ANY;
|
||||
}
|
||||
|
||||
final boolean networkIdMatches = networkId == otherNetworkId;
|
||||
if (!networkIdMatches && networkId != NETWORK_ID_ANY && otherNetworkId != NETWORK_ID_ANY) {
|
||||
// Network IDs don't match (e.g., 1 & 2 or unset & 1) and neither is a wildcard
|
||||
return MATCH_NONE;
|
||||
}
|
||||
|
||||
if (networkIdMatches && otherNetworkId != NETWORK_ID_NOT_SET
|
||||
&& otherNetworkId != NETWORK_ID_ANY) {
|
||||
// Network ID matches (they're set to the same ID)
|
||||
return MATCH_EXACT;
|
||||
}
|
||||
|
||||
// So now, network IDs aren't set or at least one is a wildcard
|
||||
|
||||
final boolean bssidMatches = bssid.equals(otherBssid);
|
||||
final boolean otherBssidIsWildcard = otherBssid.equals(BSSID_ANY);
|
||||
if (bssidMatches && !otherBssidIsWildcard) {
|
||||
// BSSID matches (and neither is a wildcard)
|
||||
return MATCH_STRONG;
|
||||
}
|
||||
|
||||
if (!bssidMatches && !bssid.equals(BSSID_ANY) && !otherBssidIsWildcard) {
|
||||
// BSSIDs don't match (e.g., 00:24:21:21:42:12 & 42:12:44:21:22:52)
|
||||
// and neither is a wildcard
|
||||
return MATCH_NONE;
|
||||
}
|
||||
|
||||
// So now, BSSIDs are both wildcards
|
||||
|
||||
final boolean ssidMatches = ssid.equals(otherSsid);
|
||||
if (ssidMatches) {
|
||||
// SSID matches
|
||||
return MATCH_WEAK;
|
||||
}
|
||||
|
||||
return MATCH_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see #matches(int, String, String)
|
||||
* @see #equals(Object)
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// Two equal() objects must have same hashCode.
|
||||
// With Wi-Fi, the broadest match is if two SSIDs are the same. The finer-grained matches
|
||||
// imply this (for example, the same network IDs means the same WifiConfiguration which
|
||||
// means the same SSID).
|
||||
// See #matches for the exact matching algorithm we use.
|
||||
return ssid != null ? ssid.hashCode() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see #matches(int, String, String)
|
||||
* @see #hashCode()
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!o.getClass().equals(getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final AccessPointState other = (AccessPointState) o;
|
||||
|
||||
// To see which conditions cause two AccessPointStates to be equal, see
|
||||
// where #matches returns MATCH_WEAK or greater.
|
||||
|
||||
return matches(other.networkId, other.bssid, other.ssid, other.security) >= MATCH_WEAK;
|
||||
}
|
||||
|
||||
public int matchesWifiConfiguration(WifiConfiguration wifiConfig) {
|
||||
String security = getWifiConfigurationSecurity(wifiConfig);
|
||||
return matches(wifiConfig.networkId, wifiConfig.BSSID, wifiConfig.SSID, security);
|
||||
}
|
||||
|
||||
String getSummarizedStatus() {
|
||||
StringBuilder sb = mSummaryBuilder;
|
||||
sb.delete(0, sb.length());
|
||||
|
||||
if (primary && status != null) {
|
||||
buildSummary(sb, WifiStatus.getPrintable(mContext, status), true);
|
||||
|
||||
} else if (!seen) {
|
||||
buildSummary(sb, SUMMARY_NOT_IN_RANGE, true);
|
||||
|
||||
// Remembered comes second in this case
|
||||
if (!primary && configured) {
|
||||
buildSummary(sb, SUMMARY_REMEMBERED, true);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (configured && disabled) {
|
||||
// The connection failure overrides all in this case
|
||||
return SUMMARY_CONNECTION_FAILED;
|
||||
}
|
||||
|
||||
// Remembered comes first in this case
|
||||
if (!primary && configured) {
|
||||
buildSummary(sb, SUMMARY_REMEMBERED, true);
|
||||
}
|
||||
|
||||
// If it is seen (and not the primary), show the security type
|
||||
String verboseSecurity = getVerboseSecurity();
|
||||
if (verboseSecurity != null) {
|
||||
buildSummary(sb, verboseSecurity, true);
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getVerboseSecurity() {
|
||||
if (WEP.equals(security)) {
|
||||
return LOCALIZED_VERBOSE_WEP;
|
||||
} else if (WPA.equals(security)) {
|
||||
return LOCALIZED_VERBOSE_WPA;
|
||||
} else if (WPA2.equals(security)) {
|
||||
return LOCALIZED_VERBOSE_WPA2;
|
||||
} else if (OPEN.equals(security)) {
|
||||
return LOCALIZED_VERBOSE_OPEN;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void buildSummary(StringBuilder sb, String string, boolean autoLowerCaseFirstLetter) {
|
||||
if (sb.length() == 0) {
|
||||
sb.append(string);
|
||||
} else {
|
||||
sb.append(", ");
|
||||
if (autoLowerCaseFirstLetter) {
|
||||
// Convert first letter to lowercase
|
||||
sb.append(Character.toLowerCase(string.charAt(0))).append(string, 1,
|
||||
string.length());
|
||||
} else {
|
||||
sb.append(string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int compareTo(AccessPointState other) {
|
||||
// This ranks the states for displaying in the AP list, not for
|
||||
// connecting to (wpa_supplicant does that using the WifiConfiguration's
|
||||
// priority field).
|
||||
|
||||
// Clarity > efficiency, of this logic:
|
||||
int comparison;
|
||||
|
||||
// Primary
|
||||
comparison = (other.primary ? 1 : 0) - (primary ? 1 : 0);
|
||||
if (comparison != 0) return comparison;
|
||||
|
||||
// Currently seen (similar to, but not always the same as within range)
|
||||
comparison = (other.seen ? 1 : 0) - (seen ? 1 : 0);
|
||||
if (comparison != 0) return comparison;
|
||||
|
||||
// Configured
|
||||
comparison = (other.configured ? 1 : 0) - (configured ? 1 : 0);
|
||||
if (comparison != 0) return comparison;
|
||||
|
||||
if (!configured) {
|
||||
// Neither are configured
|
||||
|
||||
// Open network
|
||||
comparison = (hasSecurity() ? 1 : 0) - (other.hasSecurity() ? 1 : 0);
|
||||
if (comparison != 0) return comparison;
|
||||
}
|
||||
|
||||
// Signal strength
|
||||
comparison = (int) (other.signalForSorting - signalForSorting);
|
||||
if (comparison != 0) return comparison;
|
||||
|
||||
// Alphabetical
|
||||
return ssid.compareToIgnoreCase(other.ssid);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return ssid + " (" + bssid + ", " + networkId + ", " + super.toString() + ")";
|
||||
}
|
||||
|
||||
/** Implement the Parcelable interface */
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(bssid);
|
||||
dest.writeInt(configured ? 1 : 0);
|
||||
dest.writeInt(ipAddress);
|
||||
dest.writeInt(linkSpeed);
|
||||
dest.writeInt(networkId);
|
||||
dest.writeInt(primary ? 1 : 0);
|
||||
dest.writeInt(priority);
|
||||
dest.writeInt(hiddenSsid ? 1 : 0);
|
||||
dest.writeString(security);
|
||||
dest.writeInt(seen ? 1 : 0);
|
||||
dest.writeInt(disabled ? 1 : 0);
|
||||
dest.writeInt(signal);
|
||||
dest.writeString(ssid);
|
||||
dest.writeString(status != null ? status.toString() : null);
|
||||
dest.writeString(mPassword);
|
||||
dest.writeInt(mConfigHadPassword ? 1 : 0);
|
||||
dest.writeInt(mWepPasswordType);
|
||||
}
|
||||
|
||||
/** Implement the Parcelable interface */
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Implement the Parcelable interface */
|
||||
public static final Creator<AccessPointState> CREATOR =
|
||||
new Creator<AccessPointState>() {
|
||||
public AccessPointState createFromParcel(Parcel in) {
|
||||
AccessPointState state = new AccessPointState();
|
||||
state.bssid = in.readString();
|
||||
state.configured = in.readInt() == 1;
|
||||
state.ipAddress = in.readInt();
|
||||
state.linkSpeed = in.readInt();
|
||||
state.networkId = in.readInt();
|
||||
state.primary = in.readInt() == 1;
|
||||
state.priority = in.readInt();
|
||||
state.hiddenSsid = in.readInt() == 1;
|
||||
state.security = in.readString();
|
||||
state.seen = in.readInt() == 1;
|
||||
state.disabled = in.readInt() == 1;
|
||||
state.signal = in.readInt();
|
||||
state.ssid = in.readString();
|
||||
String statusStr = in.readString();
|
||||
if (statusStr != null) {
|
||||
state.status = NetworkInfo.DetailedState.valueOf(statusStr);
|
||||
}
|
||||
state.mPassword = in.readString();
|
||||
state.mConfigHadPassword = in.readInt() == 1;
|
||||
state.mWepPasswordType = in.readInt();
|
||||
return state;
|
||||
}
|
||||
|
||||
public AccessPointState[] newArray(int size) {
|
||||
return new AccessPointState[size];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
180
src/com/android/settings/wifi/IpSettings.java
Normal file
180
src/com/android/settings/wifi/IpSettings.java
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.EditTextPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.provider.Settings.System;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class IpSettings extends PreferenceActivity implements Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final String KEY_USE_STATIC_IP = "use_static_ip";
|
||||
|
||||
private String[] mSettingNames = {
|
||||
System.WIFI_STATIC_IP, System.WIFI_STATIC_GATEWAY, System.WIFI_STATIC_NETMASK,
|
||||
System.WIFI_STATIC_DNS1, System.WIFI_STATIC_DNS2
|
||||
};
|
||||
|
||||
private String[] mPreferenceKeys = {
|
||||
"ip_address", "gateway", "netmask", "dns1", "dns2"
|
||||
};
|
||||
|
||||
private CheckBoxPreference mUseStaticIpCheckBox;
|
||||
|
||||
private static final int MENU_ITEM_SAVE = Menu.FIRST;
|
||||
private static final int MENU_ITEM_CANCEL = Menu.FIRST + 1;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.ip_settings);
|
||||
|
||||
mUseStaticIpCheckBox = (CheckBoxPreference) findPreference(KEY_USE_STATIC_IP);
|
||||
|
||||
for (int i = 0; i < mPreferenceKeys.length; i++) {
|
||||
Preference preference = findPreference(mPreferenceKeys[i]);
|
||||
preference.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
updateUi();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
updateSettingsProvider();
|
||||
}
|
||||
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
String value = (String) newValue;
|
||||
|
||||
if (!isIpAddress(value)) {
|
||||
Toast.makeText(this, R.string.wifi_ip_settings_invalid_ip, Toast.LENGTH_LONG).show();
|
||||
return false;
|
||||
}
|
||||
|
||||
preference.setSummary(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isIpAddress(String value) {
|
||||
|
||||
int start = 0;
|
||||
int end = value.indexOf('.');
|
||||
int numBlocks = 0;
|
||||
|
||||
while (start < value.length()) {
|
||||
|
||||
if (end == -1) {
|
||||
end = value.length();
|
||||
}
|
||||
|
||||
try {
|
||||
int block = Integer.parseInt(value.substring(start, end));
|
||||
if ((block > 255) || (block < 0)) {
|
||||
return false;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
numBlocks++;
|
||||
|
||||
start = end + 1;
|
||||
end = value.indexOf('.', start);
|
||||
}
|
||||
|
||||
return numBlocks == 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
|
||||
menu.add(0, MENU_ITEM_SAVE, 0, R.string.wifi_ip_settings_menu_save)
|
||||
.setIcon(android.R.drawable.ic_menu_save);
|
||||
|
||||
menu.add(0, MENU_ITEM_CANCEL, 0, R.string.wifi_ip_settings_menu_cancel)
|
||||
.setIcon(android.R.drawable.ic_menu_close_clear_cancel);
|
||||
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
|
||||
switch (item.getItemId()) {
|
||||
|
||||
case MENU_ITEM_SAVE:
|
||||
updateSettingsProvider();
|
||||
finish();
|
||||
return true;
|
||||
|
||||
case MENU_ITEM_CANCEL:
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void updateUi() {
|
||||
ContentResolver contentResolver = getContentResolver();
|
||||
|
||||
mUseStaticIpCheckBox.setChecked(System.getInt(contentResolver,
|
||||
System.WIFI_USE_STATIC_IP, 0) != 0);
|
||||
|
||||
for (int i = 0; i < mSettingNames.length; i++) {
|
||||
EditTextPreference preference = (EditTextPreference) findPreference(mPreferenceKeys[i]);
|
||||
String settingValue = System.getString(contentResolver, mSettingNames[i]);
|
||||
preference.setText(settingValue);
|
||||
preference.setSummary(settingValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSettingsProvider() {
|
||||
ContentResolver contentResolver = getContentResolver();
|
||||
|
||||
System.putInt(contentResolver, System.WIFI_USE_STATIC_IP,
|
||||
mUseStaticIpCheckBox.isChecked() ? 1 : 0);
|
||||
|
||||
for (int i = 0; i < mSettingNames.length; i++) {
|
||||
EditTextPreference preference = (EditTextPreference) findPreference(mPreferenceKeys[i]);
|
||||
System.putString(contentResolver, mSettingNames[i], preference.getText());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
188
src/com/android/settings/wifi/WifiEnabler.java
Normal file
188
src/com/android/settings/wifi/WifiEnabler.java
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi;
|
||||
|
||||
import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
|
||||
import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
|
||||
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
|
||||
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
|
||||
import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.preference.Preference;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
|
||||
public class WifiEnabler implements Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final boolean LOCAL_LOGD = Config.LOGD || WifiLayer.LOGV;
|
||||
private static final String TAG = "SettingsWifiEnabler";
|
||||
|
||||
private final Context mContext;
|
||||
private final WifiManager mWifiManager;
|
||||
private final CheckBoxPreference mWifiCheckBoxPref;
|
||||
private final CharSequence mOriginalSummary;
|
||||
|
||||
private final IntentFilter mWifiStateFilter;
|
||||
private final BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
|
||||
handleWifiStateChanged(
|
||||
intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WIFI_STATE_UNKNOWN),
|
||||
intent.getIntExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE,
|
||||
WIFI_STATE_UNKNOWN));
|
||||
} else if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
|
||||
handleNetworkStateChanged(
|
||||
(NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public WifiEnabler(Context context, WifiManager wifiManager,
|
||||
CheckBoxPreference wifiCheckBoxPreference) {
|
||||
mContext = context;
|
||||
mWifiCheckBoxPref = wifiCheckBoxPreference;
|
||||
mWifiManager = wifiManager;
|
||||
|
||||
mOriginalSummary = wifiCheckBoxPreference.getSummary();
|
||||
wifiCheckBoxPreference.setPersistent(false);
|
||||
|
||||
mWifiStateFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
|
||||
mWifiStateFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
int state = mWifiManager.getWifiState();
|
||||
// This is the widget enabled state, not the preference toggled state
|
||||
mWifiCheckBoxPref.setEnabled(state == WIFI_STATE_ENABLED || state == WIFI_STATE_DISABLED
|
||||
|| state == WIFI_STATE_UNKNOWN);
|
||||
|
||||
mContext.registerReceiver(mWifiStateReceiver, mWifiStateFilter);
|
||||
mWifiCheckBoxPref.setOnPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
mContext.unregisterReceiver(mWifiStateReceiver);
|
||||
mWifiCheckBoxPref.setOnPreferenceChangeListener(null);
|
||||
}
|
||||
|
||||
public boolean onPreferenceChange(Preference preference, Object value) {
|
||||
// Turn on/off Wi-Fi
|
||||
setWifiEnabled((Boolean) value);
|
||||
|
||||
// Don't update UI to opposite state until we're sure
|
||||
return false;
|
||||
}
|
||||
|
||||
private void setWifiEnabled(final boolean enable) {
|
||||
// Disable button
|
||||
mWifiCheckBoxPref.setEnabled(false);
|
||||
|
||||
if (!mWifiManager.setWifiEnabled(enable)) {
|
||||
mWifiCheckBoxPref.setSummary(enable ? R.string.error_starting : R.string.error_stopping);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleWifiStateChanged(int wifiState, int previousWifiState) {
|
||||
|
||||
if (LOCAL_LOGD) {
|
||||
Log.d(TAG, "Received wifi state changed from "
|
||||
+ getHumanReadableWifiState(previousWifiState) + " to "
|
||||
+ getHumanReadableWifiState(wifiState));
|
||||
}
|
||||
|
||||
if (wifiState == WIFI_STATE_DISABLED || wifiState == WIFI_STATE_ENABLED) {
|
||||
mWifiCheckBoxPref.setChecked(wifiState == WIFI_STATE_ENABLED);
|
||||
mWifiCheckBoxPref
|
||||
.setSummary(wifiState == WIFI_STATE_DISABLED ? mOriginalSummary : null);
|
||||
|
||||
mWifiCheckBoxPref.setEnabled(isEnabledByDependency());
|
||||
|
||||
} else if (wifiState == WIFI_STATE_DISABLING || wifiState == WIFI_STATE_ENABLING) {
|
||||
mWifiCheckBoxPref.setSummary(wifiState == WIFI_STATE_ENABLING ? R.string.wifi_starting
|
||||
: R.string.wifi_stopping);
|
||||
|
||||
} else if (wifiState == WIFI_STATE_UNKNOWN) {
|
||||
int message = R.string.wifi_error;
|
||||
if (previousWifiState == WIFI_STATE_ENABLING) message = R.string.error_starting;
|
||||
else if (previousWifiState == WIFI_STATE_DISABLING) message = R.string.error_stopping;
|
||||
|
||||
mWifiCheckBoxPref.setChecked(false);
|
||||
mWifiCheckBoxPref.setSummary(message);
|
||||
mWifiCheckBoxPref.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleNetworkStateChanged(NetworkInfo networkInfo) {
|
||||
|
||||
if (LOCAL_LOGD) {
|
||||
Log.d(TAG, "Received network state changed to " + networkInfo);
|
||||
}
|
||||
|
||||
if (mWifiManager.isWifiEnabled()) {
|
||||
String summary = WifiStatus.getStatus(mContext,
|
||||
mWifiManager.getConnectionInfo().getSSID(), networkInfo.getDetailedState());
|
||||
mWifiCheckBoxPref.setSummary(summary);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEnabledByDependency() {
|
||||
Preference dep = getDependencyPreference();
|
||||
if (dep == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !dep.shouldDisableDependents();
|
||||
}
|
||||
|
||||
private Preference getDependencyPreference() {
|
||||
String depKey = mWifiCheckBoxPref.getDependency();
|
||||
if (TextUtils.isEmpty(depKey)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return mWifiCheckBoxPref.getPreferenceManager().findPreference(depKey);
|
||||
}
|
||||
|
||||
private static String getHumanReadableWifiState(int wifiState) {
|
||||
switch (wifiState) {
|
||||
case WIFI_STATE_DISABLED:
|
||||
return "Disabled";
|
||||
case WIFI_STATE_DISABLING:
|
||||
return "Disabling";
|
||||
case WIFI_STATE_ENABLED:
|
||||
return "Enabled";
|
||||
case WIFI_STATE_ENABLING:
|
||||
return "Enabling";
|
||||
case WIFI_STATE_UNKNOWN:
|
||||
return "Unknown";
|
||||
default:
|
||||
return "Some other state!";
|
||||
}
|
||||
}
|
||||
}
|
||||
1302
src/com/android/settings/wifi/WifiLayer.java
Normal file
1302
src/com/android/settings/wifi/WifiLayer.java
Normal file
File diff suppressed because it is too large
Load Diff
438
src/com/android/settings/wifi/WifiSettings.java
Normal file
438
src/com/android/settings/wifi/WifiSettings.java
Normal file
@@ -0,0 +1,438 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi;
|
||||
|
||||
import com.android.settings.ProgressCategory;
|
||||
import com.android.settings.R;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.AdapterView.AdapterContextMenuInfo;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
/**
|
||||
* Settings screen for WiFi. This will be launched from the main system settings.
|
||||
*/
|
||||
public class WifiSettings extends PreferenceActivity implements WifiLayer.Callback,
|
||||
DialogInterface.OnDismissListener {
|
||||
|
||||
private static final String TAG = "WifiSettings";
|
||||
|
||||
//============================
|
||||
// Preference/activity member variables
|
||||
//============================
|
||||
|
||||
private static final String INSTANCE_KEY_DIALOG_BUNDLE =
|
||||
"com.android.settings.wifi.WifiSettings:dialogBundle";
|
||||
/*
|
||||
* We don't use Activity's dialog management because AlertDialog isn't fully
|
||||
* able to change many of its features after it's been created, and the
|
||||
* dialog management only creates once.
|
||||
*/
|
||||
private Dialog mDialog;
|
||||
|
||||
private static final String KEY_ADD_OTHER_NETWORK = "add_other_network";
|
||||
|
||||
private static final int CONTEXT_MENU_ID_CONNECT = Menu.FIRST;
|
||||
private static final int CONTEXT_MENU_ID_FORGET = Menu.FIRST + 1;
|
||||
private static final int CONTEXT_MENU_ID_CHANGE_PASSWORD = Menu.FIRST + 2;
|
||||
|
||||
private static final int MENU_ID_SCAN = Menu.FIRST;
|
||||
private static final int MENU_ID_ADVANCED = Menu.FIRST + 1;
|
||||
|
||||
private static final String KEY_WIFI_ENABLED = "wifi_enabled";
|
||||
private static final String KEY_OPEN_NETWORK_NOTIFICATIONS_ENABLED =
|
||||
"open_network_notifications_enabled";
|
||||
private static final String KEY_ACCESS_POINTS = "access_points";
|
||||
|
||||
private ProgressCategory mApCategory;
|
||||
private CheckBoxPreference mWifiEnabled;
|
||||
private WifiEnabler mWifiEnabler;
|
||||
private CheckBoxPreference mOpenNetworkNotificationsEnabled;
|
||||
private Preference mAddOtherNetwork;
|
||||
|
||||
private WeakHashMap<AccessPointState, AccessPointPreference> mAps;
|
||||
|
||||
//============================
|
||||
// Wifi member variables
|
||||
//============================
|
||||
|
||||
private WifiLayer mWifiLayer;
|
||||
|
||||
//============================
|
||||
// Activity lifecycle
|
||||
//============================
|
||||
|
||||
public WifiSettings() {
|
||||
mAps = new WeakHashMap<AccessPointState, AccessPointPreference>();
|
||||
mWifiLayer = new WifiLayer(this, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
onCreatePreferences();
|
||||
mWifiLayer.onCreate();
|
||||
|
||||
onCreatedWifi();
|
||||
mWifiLayer.onCreatedCallback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shouldn't have any dependency on the wifi layer.
|
||||
*/
|
||||
private void onCreatePreferences() {
|
||||
addPreferencesFromResource(R.xml.wifi_settings);
|
||||
|
||||
final PreferenceScreen preferenceScreen = getPreferenceScreen();
|
||||
|
||||
mApCategory = (ProgressCategory) preferenceScreen.findPreference(KEY_ACCESS_POINTS);
|
||||
// We don't want the ordering to be the order preferences are added,
|
||||
// instead we want*:
|
||||
// 1) preferred, visible APs
|
||||
// 2) visible APs
|
||||
// 3) preferred, APs out of range
|
||||
// * this ordering logic is in AccessPointPreference's compareTo
|
||||
mApCategory.setOrderingAsAdded(false);
|
||||
|
||||
mWifiEnabled = (CheckBoxPreference) preferenceScreen.findPreference(KEY_WIFI_ENABLED);
|
||||
mWifiEnabler = new WifiEnabler(this, (WifiManager) getSystemService(WIFI_SERVICE),
|
||||
mWifiEnabled);
|
||||
|
||||
mOpenNetworkNotificationsEnabled = (CheckBoxPreference) preferenceScreen
|
||||
.findPreference(KEY_OPEN_NETWORK_NOTIFICATIONS_ENABLED);
|
||||
mOpenNetworkNotificationsEnabled.setChecked(Settings.System.getInt(getContentResolver(),
|
||||
Settings.System.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1);
|
||||
|
||||
mAddOtherNetwork = preferenceScreen.findPreference(KEY_ADD_OTHER_NETWORK);
|
||||
|
||||
registerForContextMenu(getListView());
|
||||
}
|
||||
|
||||
private void onCreatedWifi() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mWifiLayer.onResume();
|
||||
mWifiEnabler.resume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mWifiLayer.onPause();
|
||||
mWifiEnabler.pause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
if (mDialog != null) {
|
||||
mDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
|
||||
menu.add(0, MENU_ID_SCAN, 0, R.string.scan_wifi)
|
||||
.setIcon(R.drawable.ic_menu_scan_network);
|
||||
|
||||
menu.add(0, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced)
|
||||
.setIcon(R.drawable.ic_menu_manage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
super.onOptionsItemSelected(item);
|
||||
|
||||
switch (item.getItemId()) {
|
||||
|
||||
case MENU_ID_SCAN:
|
||||
mWifiLayer.attemptScan();
|
||||
return true;
|
||||
|
||||
case MENU_ID_ADVANCED:
|
||||
Intent intent = new Intent(this, IpSettings.class);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
if (mDialog != null) {
|
||||
Bundle dialogBundle = mDialog.onSaveInstanceState();
|
||||
outState.putBundle(INSTANCE_KEY_DIALOG_BUNDLE, dialogBundle);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle state) {
|
||||
super.onRestoreInstanceState(state);
|
||||
|
||||
Bundle dialogBundle = state.getBundle(INSTANCE_KEY_DIALOG_BUNDLE);
|
||||
if (dialogBundle != null) {
|
||||
mDialog = new AccessPointDialog(this, mWifiLayer);
|
||||
mDialog.onRestoreInstanceState(dialogBundle);
|
||||
showDialog(mDialog);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
if (dialog == mDialog) {
|
||||
mDialog = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
|
||||
AccessPointState state = getStateFromMenuInfo(menuInfo);
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
menu.setHeaderTitle(state.getHumanReadableSsid());
|
||||
|
||||
if (state.isConnectable()) {
|
||||
menu.add(0, CONTEXT_MENU_ID_CONNECT, 0, R.string.wifi_context_menu_connect);
|
||||
}
|
||||
|
||||
if (state.isForgetable()) {
|
||||
menu.add(0, CONTEXT_MENU_ID_FORGET, 1, R.string.wifi_context_menu_forget);
|
||||
|
||||
if (state.hasPassword()) {
|
||||
menu.add(0, CONTEXT_MENU_ID_CHANGE_PASSWORD, 2,
|
||||
R.string.wifi_context_menu_change_password);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
|
||||
AccessPointState state = getStateFromMenuInfo(item.getMenuInfo());
|
||||
if (state == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (item.getItemId()) {
|
||||
|
||||
case CONTEXT_MENU_ID_CONNECT:
|
||||
connectToNetwork(state);
|
||||
return true;
|
||||
|
||||
case CONTEXT_MENU_ID_FORGET:
|
||||
mWifiLayer.forgetNetwork(state);
|
||||
return true;
|
||||
|
||||
case CONTEXT_MENU_ID_CHANGE_PASSWORD:
|
||||
showAccessPointDialog(state, AccessPointDialog.MODE_CONFIGURE);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decides what needs to happen to connect to a particular access point. If
|
||||
* it is secured and doesn't already have a password, it will bring up a
|
||||
* password box. Otherwise it will just connect.
|
||||
*/
|
||||
private void connectToNetwork(AccessPointState state) {
|
||||
if (state.hasSecurity() && !state.hasPassword()) {
|
||||
showAccessPointDialog(state, AccessPointDialog.MODE_INFO);
|
||||
} else {
|
||||
mWifiLayer.connectToNetwork(state);
|
||||
}
|
||||
}
|
||||
|
||||
private AccessPointState getStateFromMenuInfo(ContextMenuInfo menuInfo) {
|
||||
if ((menuInfo == null) || !(menuInfo instanceof AdapterContextMenuInfo)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
AdapterContextMenuInfo adapterMenuInfo = (AdapterContextMenuInfo) menuInfo;
|
||||
Preference pref = (Preference) getPreferenceScreen().getRootAdapter().getItem(
|
||||
adapterMenuInfo.position);
|
||||
if (pref == null || !(pref instanceof AccessPointPreference)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ((AccessPointPreference) pref).getAccessPointState();
|
||||
}
|
||||
|
||||
//============================
|
||||
// Preference callbacks
|
||||
//============================
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
|
||||
super.onPreferenceTreeClick(preferenceScreen, preference);
|
||||
|
||||
if (preference == mAddOtherNetwork) {
|
||||
showAddOtherNetworkDialog();
|
||||
} else if (preference == mOpenNetworkNotificationsEnabled) {
|
||||
Settings.System.putInt(getContentResolver(),
|
||||
Settings.System.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
|
||||
mOpenNetworkNotificationsEnabled.isChecked() ? 1 : 0);
|
||||
} else if (preference instanceof AccessPointPreference) {
|
||||
AccessPointState state = ((AccessPointPreference) preference).getAccessPointState();
|
||||
showAccessPointDialog(state, AccessPointDialog.MODE_INFO);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//============================
|
||||
// Wifi-related
|
||||
//============================
|
||||
|
||||
public WifiLayer getWifiLayer() {
|
||||
return mWifiLayer;
|
||||
}
|
||||
|
||||
private void showAddOtherNetworkDialog() {
|
||||
AccessPointDialog dialog = new AccessPointDialog(this, mWifiLayer);
|
||||
dialog.setState(new AccessPointState(this));
|
||||
dialog.setMode(AccessPointDialog.MODE_CONFIGURE);
|
||||
dialog.setTitle(R.string.wifi_add_other_network);
|
||||
dialog.setAutoSecurityAllowed(false);
|
||||
showDialog(dialog);
|
||||
}
|
||||
|
||||
public void showAccessPointDialog(AccessPointState state, int mode) {
|
||||
AccessPointDialog dialog = new AccessPointDialog(this, mWifiLayer);
|
||||
dialog.setMode(mode);
|
||||
dialog.setState(state);
|
||||
showDialog(dialog);
|
||||
}
|
||||
|
||||
private void showDialog(Dialog dialog) {
|
||||
// Have only one dialog open at a time
|
||||
if (mDialog != null) {
|
||||
mDialog.dismiss();
|
||||
}
|
||||
|
||||
mDialog = dialog;
|
||||
dialog.setOnDismissListener(this);
|
||||
if (dialog != null) {
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
//============================
|
||||
// Wifi callbacks
|
||||
//============================
|
||||
|
||||
public void onError(int messageResId) {
|
||||
Toast.makeText(this, messageResId, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
public void onScanningStatusChanged(boolean started) {
|
||||
mApCategory.setProgress(started);
|
||||
}
|
||||
|
||||
public void onAccessPointSetChanged(AccessPointState ap, boolean added) {
|
||||
|
||||
AccessPointPreference pref = mAps.get(ap);
|
||||
|
||||
if (WifiLayer.LOGV) {
|
||||
Log.v(TAG, "onAccessPointSetChanged with " + ap + " and "
|
||||
+ (added ? "added" : "removed") + ", found pref " + pref);
|
||||
}
|
||||
|
||||
if (added) {
|
||||
|
||||
if (pref == null) {
|
||||
pref = new AccessPointPreference(this, ap);
|
||||
mAps.put(ap, pref);
|
||||
} else {
|
||||
pref.setEnabled(true);
|
||||
}
|
||||
|
||||
mApCategory.addPreference(pref);
|
||||
|
||||
} else {
|
||||
|
||||
mAps.remove(ap);
|
||||
|
||||
if (pref != null) {
|
||||
mApCategory.removePreference(pref);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void onAccessPointsStateChanged(boolean enabled) {
|
||||
if (enabled) {
|
||||
mApCategory.setEnabled(true);
|
||||
} else {
|
||||
mApCategory.removeAll();
|
||||
mAps.clear();
|
||||
}
|
||||
|
||||
mAddOtherNetwork.setEnabled(enabled);
|
||||
}
|
||||
|
||||
public void onRetryPassword(AccessPointState ap) {
|
||||
|
||||
if ((mDialog != null) && mDialog.isShowing()) {
|
||||
// If we're already showing a dialog, ignore this request
|
||||
return;
|
||||
}
|
||||
|
||||
showAccessPointDialog(ap, AccessPointDialog.MODE_RETRY_PASSWORD);
|
||||
}
|
||||
|
||||
}
|
||||
152
src/com/android/settings/wifi/WifiStatus.java
Normal file
152
src/com/android/settings/wifi/WifiStatus.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.wifi;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.text.TextUtils;
|
||||
|
||||
public class WifiStatus {
|
||||
|
||||
// e.g., "Connecting"
|
||||
public static String sScanning;
|
||||
public static String sConnecting;
|
||||
public static String sAuthenticating;
|
||||
public static String sObtainingIp;
|
||||
public static String sConnected;
|
||||
public static String sDisconnecting;
|
||||
public static String sDisconnected;
|
||||
public static String sFailed;
|
||||
|
||||
// e.g., "Connecting to %1$s"
|
||||
public static String sScanningFragment;
|
||||
public static String sConnectingFragment;
|
||||
public static String sAuthenticatingFragment;
|
||||
public static String sObtainingIpFragment;
|
||||
public static String sConnectedFragment;
|
||||
public static String sDisconnectingFragment;
|
||||
public static String sDisconnectedFragment;
|
||||
public static String sFailedFragment;
|
||||
|
||||
private static void fillStrings(Context context) {
|
||||
sScanning = context.getString(R.string.status_scanning);
|
||||
sConnecting = context.getString(R.string.status_connecting);
|
||||
sAuthenticating = context.getString(R.string.status_authenticating);
|
||||
sObtainingIp = context.getString(R.string.status_obtaining_ip);
|
||||
sConnected = context.getString(R.string.status_connected);
|
||||
sDisconnecting = context.getString(R.string.status_disconnecting);
|
||||
sDisconnected = context.getString(R.string.status_disconnected);
|
||||
sFailed = context.getString(R.string.status_failed);
|
||||
|
||||
sScanningFragment = context.getString(R.string.fragment_status_scanning);
|
||||
sConnectingFragment = context.getString(R.string.fragment_status_connecting);
|
||||
sAuthenticatingFragment = context.getString(R.string.fragment_status_authenticating);
|
||||
sObtainingIpFragment = context.getString(R.string.fragment_status_obtaining_ip);
|
||||
sConnectedFragment = context.getString(R.string.fragment_status_connected);
|
||||
sDisconnectingFragment = context.getString(R.string.fragment_status_disconnecting);
|
||||
sDisconnectedFragment = context.getString(R.string.fragment_status_disconnected);
|
||||
sFailedFragment = context.getString(R.string.fragment_status_failed);
|
||||
}
|
||||
|
||||
public static String getStatus(Context context, String ssid,
|
||||
NetworkInfo.DetailedState detailedState) {
|
||||
|
||||
if (!TextUtils.isEmpty(ssid) && isLiveConnection(detailedState)) {
|
||||
return getPrintableFragment(context, detailedState, ssid);
|
||||
} else {
|
||||
return getPrintable(context, detailedState);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isLiveConnection(NetworkInfo.DetailedState detailedState) {
|
||||
return detailedState != NetworkInfo.DetailedState.DISCONNECTED
|
||||
&& detailedState != NetworkInfo.DetailedState.FAILED
|
||||
&& detailedState != NetworkInfo.DetailedState.IDLE
|
||||
&& detailedState != NetworkInfo.DetailedState.SCANNING;
|
||||
}
|
||||
|
||||
public static String getPrintable(Context context,
|
||||
NetworkInfo.DetailedState detailedState) {
|
||||
|
||||
if (sScanning == null) {
|
||||
fillStrings(context);
|
||||
}
|
||||
|
||||
switch (detailedState) {
|
||||
case AUTHENTICATING:
|
||||
return sAuthenticating;
|
||||
case CONNECTED:
|
||||
return sConnected;
|
||||
case CONNECTING:
|
||||
return sConnecting;
|
||||
case DISCONNECTED:
|
||||
return sDisconnected;
|
||||
case DISCONNECTING:
|
||||
return sDisconnecting;
|
||||
case FAILED:
|
||||
return sFailed;
|
||||
case OBTAINING_IPADDR:
|
||||
return sObtainingIp;
|
||||
case SCANNING:
|
||||
return sScanning;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getPrintableFragment(Context context,
|
||||
NetworkInfo.DetailedState detailedState, String apName) {
|
||||
|
||||
if (sScanningFragment == null) {
|
||||
fillStrings(context);
|
||||
}
|
||||
|
||||
String fragment = null;
|
||||
switch (detailedState) {
|
||||
case AUTHENTICATING:
|
||||
fragment = sAuthenticatingFragment;
|
||||
break;
|
||||
case CONNECTED:
|
||||
fragment = sConnectedFragment;
|
||||
break;
|
||||
case CONNECTING:
|
||||
fragment = sConnectingFragment;
|
||||
break;
|
||||
case DISCONNECTED:
|
||||
fragment = sDisconnectedFragment;
|
||||
break;
|
||||
case DISCONNECTING:
|
||||
fragment = sDisconnectingFragment;
|
||||
break;
|
||||
case FAILED:
|
||||
fragment = sFailedFragment;
|
||||
break;
|
||||
case OBTAINING_IPADDR:
|
||||
fragment = sObtainingIpFragment;
|
||||
break;
|
||||
case SCANNING:
|
||||
fragment = sScanningFragment;
|
||||
break;
|
||||
}
|
||||
|
||||
return String.format(fragment, apName);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user