summaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/BackupRestoreConfirmation/AndroidManifest.xml2
-rw-r--r--packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml1
-rw-r--r--packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml1
-rw-r--r--packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java33
-rw-r--r--packages/SettingsProvider/res/values/defaults.xml3
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java14
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java152
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java6
-rw-r--r--packages/SharedStorageBackup/Android.mk33
-rw-r--r--packages/SharedStorageBackup/AndroidManifest.xml29
-rw-r--r--packages/SharedStorageBackup/proguard.flags1
-rw-r--r--packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java93
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_default.pngbin0 -> 4050 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_pressed.pngbin0 -> 7760 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_zoom_default.pngbin0 -> 2642 bytes
-rw-r--r--packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_zoom_pressed.pngbin0 -> 4140 bytes
-rw-r--r--packages/SystemUI/res/drawable/ic_sysbar_zoom.xml21
-rw-r--r--packages/SystemUI/res/layout-sw600dp/status_bar.xml7
-rw-r--r--packages/SystemUI/res/values-fr-large/strings.xml2
-rw-r--r--packages/SystemUI/res/values-it-large/strings.xml4
-rw-r--r--packages/SystemUI/res/values-large/config.xml7
-rw-r--r--packages/SystemUI/res/values-ru-large/strings.xml10
-rw-r--r--packages/SystemUI/res/values-sw600dp-port/config.xml25
-rw-r--r--packages/SystemUI/res/values-sw600dp-port/dimens.xml4
-rw-r--r--packages/SystemUI/res/values-sw720dp-port/dimens.xml22
-rw-r--r--packages/SystemUI/res/values-sw720dp/config.xml25
-rw-r--r--packages/SystemUI/res/values/config.xml13
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIService.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java64
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java26
-rw-r--r--packages/VpnDialogs/Android.mk27
-rw-r--r--packages/VpnDialogs/AndroidManifest.xml22
-rw-r--r--packages/VpnDialogs/res/layout/confirm.xml61
-rw-r--r--packages/VpnDialogs/res/layout/manage.xml43
-rw-r--r--packages/VpnDialogs/res/values/strings.xml45
-rw-r--r--packages/VpnDialogs/res/values/styles.xml37
-rw-r--r--packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java116
-rw-r--r--packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java183
40 files changed, 1074 insertions, 95 deletions
diff --git a/packages/BackupRestoreConfirmation/AndroidManifest.xml b/packages/BackupRestoreConfirmation/AndroidManifest.xml
index ed9a519..19848f6 100644
--- a/packages/BackupRestoreConfirmation/AndroidManifest.xml
+++ b/packages/BackupRestoreConfirmation/AndroidManifest.xml
@@ -21,7 +21,7 @@
<uses-permission android:name="android.permission.BACKUP" />
<application android:allowClearUserData="false"
- android:killAfterRestore="false"
+ android:allowBackup="false"
android:permission="android.permission.CONFIRM_FULL_BACKUP" >
<activity android:name=".BackupRestoreConfirmation"
diff --git a/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml b/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
index 109cfff..a4564e6 100644
--- a/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
+++ b/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
@@ -37,6 +37,7 @@
android:layout_marginBottom="30dp" />
<Button android:id="@+id/button_allow"
+ android:filterTouchesWhenObscured="true"
android:text="@string/allow_backup_button_label"
android:layout_below="@id/package_name"
android:layout_height="wrap_content"
diff --git a/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml b/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
index a1f9a4a..ca99ae1 100644
--- a/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
+++ b/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
@@ -37,6 +37,7 @@
android:layout_marginBottom="30dp" />
<Button android:id="@+id/button_allow"
+ android:filterTouchesWhenObscured="true"
android:text="@string/allow_restore_button_label"
android:layout_below="@id/package_name"
android:layout_height="wrap_content"
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index 4b42067..ed413e6 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -60,6 +60,7 @@ public class BackupRestoreConfirmation extends Activity {
IBackupManager mBackupManager;
FullObserver mObserver;
int mToken;
+ boolean mDidAcknowledge;
TextView mStatusView;
Button mAllowButton;
@@ -70,6 +71,7 @@ public class BackupRestoreConfirmation extends Activity {
Context mContext;
ObserverHandler(Context context) {
mContext = context;
+ mDidAcknowledge = false;
}
@Override
@@ -98,6 +100,8 @@ public class BackupRestoreConfirmation extends Activity {
break;
case MSG_RESTORE_PACKAGE: {
+ String name = (String) msg.obj;
+ mStatusView.setText(name);
}
break;
@@ -155,11 +159,7 @@ public class BackupRestoreConfirmation extends Activity {
mAllowButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- try {
- mBackupManager.acknowledgeFullBackupOrRestore(mToken, true, mObserver);
- } catch (RemoteException e) {
- // TODO: bail gracefully if we can't contact the backup manager
- }
+ sendAcknowledgement(mToken, true, mObserver);
mAllowButton.setEnabled(false);
mDenyButton.setEnabled(false);
}
@@ -168,11 +168,7 @@ public class BackupRestoreConfirmation extends Activity {
mDenyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- try {
- mBackupManager.acknowledgeFullBackupOrRestore(mToken, false, mObserver);
- } catch (RemoteException e) {
- // TODO: bail gracefully if we can't contact the backup manager
- }
+ sendAcknowledgement(mToken, false, mObserver);
mAllowButton.setEnabled(false);
mDenyButton.setEnabled(false);
}
@@ -185,14 +181,21 @@ public class BackupRestoreConfirmation extends Activity {
// We explicitly equate departure from the UI with refusal. This includes the
// implicit configuration-changed stop/restart cycle.
- try {
- mBackupManager.acknowledgeFullBackupOrRestore(mToken, false, null);
- } catch (RemoteException e) {
- // if this fails we'll still time out with no acknowledgment
- }
+ sendAcknowledgement(mToken, false, null);
finish();
}
+ void sendAcknowledgement(int token, boolean allow, IFullBackupRestoreObserver observer) {
+ if (!mDidAcknowledge) {
+ mDidAcknowledge = true;
+ try {
+ mBackupManager.acknowledgeFullBackupOrRestore(mToken, true, mObserver);
+ } catch (RemoteException e) {
+ // TODO: bail gracefully if we can't contact the backup manager
+ }
+ }
+ }
+
/**
* The observer binder for showing backup/restore progress. This binder just bounces
* the notifications onto the main thread.
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index bf06f947..2e2768f 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -125,4 +125,7 @@
<!-- Default for Settings.Secure.LONG_PRESS_TIMEOUT_MILLIS -->
<integer name="def_long_press_timeout_millis">500</integer>
+ <!-- Default for Settings.System.POINTER_SPEED -->
+ <integer name="def_pointer_speed">0</integer>
+
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index b99c8b0..9cbf704 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -17,6 +17,8 @@
package com.android.providers.settings;
import com.android.internal.content.PackageHelper;
+import com.android.internal.telephony.BaseCommands;
+import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RILConstants;
import com.android.internal.util.XmlUtils;
import com.android.internal.widget.LockPatternUtils;
@@ -1214,6 +1216,9 @@ public class DatabaseHelper extends SQLiteOpenHelper {
loadBooleanSetting(stmt, Settings.System.NOTIFICATIONS_USE_RING_VOLUME,
R.bool.def_notifications_use_ring_volume);
+ loadIntegerSetting(stmt, Settings.System.POINTER_SPEED,
+ R.integer.def_pointer_speed);
+
} finally {
if (stmt != null) stmt.close();
}
@@ -1297,8 +1302,13 @@ public class DatabaseHelper extends SQLiteOpenHelper {
}
// Set the preferred network mode to 0 = Global, CDMA default
- int type = SystemProperties.getInt("ro.telephony.default_network",
- RILConstants.PREFERRED_NETWORK_MODE);
+ int type;
+ if (BaseCommands.getLteOnCdmaModeStatic() == Phone.LTE_ON_CDMA_TRUE) {
+ type = Phone.NT_MODE_GLOBAL;
+ } else {
+ type = SystemProperties.getInt("ro.telephony.default_network",
+ RILConstants.PREFERRED_NETWORK_MODE);
+ }
loadSetting(stmt, Settings.Secure.PREFERRED_NETWORK_MODE, type);
// Enable or disable Cell Broadcast SMS
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 45bb2b6..0c4ef7d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -55,6 +55,7 @@ import android.util.Log;
*/
public class SettingsBackupAgent extends BackupAgentHelper {
private static final boolean DEBUG = false;
+ private static final boolean DEBUG_BACKUP = DEBUG || true;
private static final String KEY_SYSTEM = "system";
private static final String KEY_SECURE = "secure";
@@ -75,6 +76,9 @@ public class SettingsBackupAgent extends BackupAgentHelper {
private static final int STATE_WIFI_CONFIG = 4;
private static final int STATE_SIZE = 5; // The number of state items
+ // Versioning of the 'full backup' format
+ private static final int FULL_BACKUP_VERSION = 1;
+
private static String[] sortedSystemKeys = null;
private static String[] sortedSecureKeys = null;
@@ -109,6 +113,8 @@ public class SettingsBackupAgent extends BackupAgentHelper {
private static String mWifiConfigFile;
public void onCreate() {
+ if (DEBUG_BACKUP) Log.d(TAG, "onCreate() invoked");
+
mSettingsHelper = new SettingsHelper(this);
super.onCreate();
@@ -151,26 +157,32 @@ public class SettingsBackupAgent extends BackupAgentHelper {
// representation of the backed-up settings.
String root = getFilesDir().getAbsolutePath();
File stage = new File(root, STAGE_FILE);
- FileOutputStream filestream = new FileOutputStream(stage);
- BufferedOutputStream bufstream = new BufferedOutputStream(filestream);
- DataOutputStream out = new DataOutputStream(bufstream);
-
- out.writeInt(systemSettingsData.length);
- out.write(systemSettingsData);
- out.writeInt(secureSettingsData.length);
- out.write(secureSettingsData);
- out.writeInt(locale.length);
- out.write(locale);
- out.writeInt(wifiSupplicantData.length);
- out.write(wifiSupplicantData);
- out.writeInt(wifiConfigData.length);
- out.write(wifiConfigData);
-
- out.flush(); // also flushes downstream
-
- // now we're set to emit the tar stream
- FullBackup.backupToTar(getPackageName(), FullBackup.DATA_TREE_TOKEN, null,
- root, stage.getAbsolutePath(), data);
+ try {
+ FileOutputStream filestream = new FileOutputStream(stage);
+ BufferedOutputStream bufstream = new BufferedOutputStream(filestream);
+ DataOutputStream out = new DataOutputStream(bufstream);
+
+ out.writeInt(FULL_BACKUP_VERSION);
+
+ out.writeInt(systemSettingsData.length);
+ out.write(systemSettingsData);
+ out.writeInt(secureSettingsData.length);
+ out.write(secureSettingsData);
+ out.writeInt(locale.length);
+ out.write(locale);
+ out.writeInt(wifiSupplicantData.length);
+ out.write(wifiSupplicantData);
+ out.writeInt(wifiConfigData.length);
+ out.write(wifiConfigData);
+
+ out.flush(); // also flushes downstream
+
+ // now we're set to emit the tar stream
+ FullBackup.backupToTar(getPackageName(), FullBackup.DATA_TREE_TOKEN, null,
+ root, stage.getAbsolutePath(), data);
+ } finally {
+ stage.delete();
+ }
}
}
@@ -199,7 +211,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
} else if (KEY_LOCALE.equals(key)) {
byte[] localeData = new byte[size];
data.readEntityData(localeData, 0, size);
- mSettingsHelper.setLocaleData(localeData);
+ mSettingsHelper.setLocaleData(localeData, size);
} else if (KEY_WIFI_CONFIG.equals(key)) {
restoreFileData(mWifiConfigFile, data);
} else {
@@ -208,6 +220,70 @@ public class SettingsBackupAgent extends BackupAgentHelper {
}
}
+ @Override
+ public void onRestoreFile(ParcelFileDescriptor data, long size,
+ int type, String domain, String relpath, long mode, long mtime)
+ throws IOException {
+ if (DEBUG_BACKUP) Log.d(TAG, "onRestoreFile() invoked");
+ // Our data is actually a blob of flattened settings data identical to that
+ // produced during incremental backups. Just unpack and apply it all in
+ // turn.
+ FileInputStream instream = new FileInputStream(data.getFileDescriptor());
+ DataInputStream in = new DataInputStream(instream);
+
+ int version = in.readInt();
+ if (DEBUG_BACKUP) Log.d(TAG, "Flattened data version " + version);
+ if (version == FULL_BACKUP_VERSION) {
+ // system settings data first
+ int nBytes = in.readInt();
+ if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of settings data");
+ byte[] buffer = new byte[nBytes];
+ in.read(buffer, 0, nBytes);
+ restoreSettings(buffer, nBytes, Settings.System.CONTENT_URI);
+
+ // secure settings
+ nBytes = in.readInt();
+ if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of secure settings data");
+ if (nBytes > buffer.length) buffer = new byte[nBytes];
+ in.read(buffer, 0, nBytes);
+ restoreSettings(buffer, nBytes, Settings.Secure.CONTENT_URI);
+
+ // locale
+ nBytes = in.readInt();
+ if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of locale data");
+ if (nBytes > buffer.length) buffer = new byte[nBytes];
+ in.read(buffer, 0, nBytes);
+ mSettingsHelper.setLocaleData(buffer, nBytes);
+
+ // wifi supplicant
+ nBytes = in.readInt();
+ if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of wifi supplicant data");
+ if (nBytes > buffer.length) buffer = new byte[nBytes];
+ in.read(buffer, 0, nBytes);
+ int retainedWifiState = enableWifi(false);
+ restoreWifiSupplicant(FILE_WIFI_SUPPLICANT, buffer, nBytes);
+ FileUtils.setPermissions(FILE_WIFI_SUPPLICANT,
+ FileUtils.S_IRUSR | FileUtils.S_IWUSR |
+ FileUtils.S_IRGRP | FileUtils.S_IWGRP,
+ Process.myUid(), Process.WIFI_UID);
+ // retain the previous WIFI state.
+ enableWifi(retainedWifiState == WifiManager.WIFI_STATE_ENABLED ||
+ retainedWifiState == WifiManager.WIFI_STATE_ENABLING);
+
+ // wifi config
+ nBytes = in.readInt();
+ if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of wifi config data");
+ if (nBytes > buffer.length) buffer = new byte[nBytes];
+ in.read(buffer, 0, nBytes);
+ restoreFileData(mWifiConfigFile, buffer, nBytes);
+
+ if (DEBUG_BACKUP) Log.d(TAG, "Full restore complete.");
+ } else {
+ data.close();
+ throw new IOException("Invalid file schema");
+ }
+ }
+
private long[] readOldChecksums(ParcelFileDescriptor oldState) throws IOException {
long[] stateChecksums = new long[STATE_SIZE];
@@ -287,6 +363,17 @@ public class SettingsBackupAgent extends BackupAgentHelper {
}
private void restoreSettings(BackupDataInput data, Uri contentUri) {
+ byte[] settings = new byte[data.getDataSize()];
+ try {
+ data.readEntityData(settings, 0, settings.length);
+ } catch (IOException ioe) {
+ Log.e(TAG, "Couldn't read entity data");
+ return;
+ }
+ restoreSettings(settings, settings.length, contentUri);
+ }
+
+ private void restoreSettings(byte[] settings, int bytes, Uri contentUri) {
if (DEBUG) Log.i(TAG, "restoreSettings: " + contentUri);
String[] whitelist = null;
if (contentUri.equals(Settings.Secure.CONTENT_URI)) {
@@ -296,15 +383,8 @@ public class SettingsBackupAgent extends BackupAgentHelper {
}
ContentValues cv = new ContentValues(2);
- byte[] settings = new byte[data.getDataSize()];
- try {
- data.readEntityData(settings, 0, settings.length);
- } catch (IOException ioe) {
- Log.e(TAG, "Couldn't read entity data");
- return;
- }
int pos = 0;
- while (pos < settings.length) {
+ while (pos < bytes) {
int length = readInt(settings, pos);
pos += 4;
String settingName = length > 0? new String(settings, pos, length) : null;
@@ -451,13 +531,16 @@ public class SettingsBackupAgent extends BackupAgentHelper {
private void restoreFileData(String filename, BackupDataInput data) {
byte[] bytes = new byte[data.getDataSize()];
if (bytes.length <= 0) return;
+ restoreFileData(filename, bytes, bytes.length);
+ }
+
+ private void restoreFileData(String filename, byte[] bytes, int size) {
try {
- data.readEntityData(bytes, 0, bytes.length);
File file = new File(filename);
if (file.exists()) file.delete();
OutputStream os = new BufferedOutputStream(new FileOutputStream(filename, true));
- os.write(bytes);
+ os.write(bytes, 0, size);
os.close();
} catch (IOException ioe) {
Log.w(TAG, "Couldn't restore " + filename);
@@ -506,15 +589,18 @@ public class SettingsBackupAgent extends BackupAgentHelper {
private void restoreWifiSupplicant(String filename, BackupDataInput data) {
byte[] bytes = new byte[data.getDataSize()];
if (bytes.length <= 0) return;
+ restoreWifiSupplicant(filename, bytes, bytes.length);
+ }
+
+ private void restoreWifiSupplicant(String filename, byte[] bytes, int size) {
try {
- data.readEntityData(bytes, 0, bytes.length);
File supplicantFile = new File(FILE_WIFI_SUPPLICANT);
if (supplicantFile.exists()) supplicantFile.delete();
copyWifiSupplicantTemplate();
OutputStream os = new BufferedOutputStream(new FileOutputStream(filename, true));
os.write("\n".getBytes());
- os.write(bytes);
+ os.write(bytes, 0, size);
os.close();
} catch (IOException ioe) {
Log.w(TAG, "Couldn't restore " + filename);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 0e75fbc..3e7d86a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -147,7 +147,7 @@ public class SettingsHelper {
* "ll" is the language code and "cc" is the country code.
* @param data the locale string in bytes.
*/
- void setLocaleData(byte[] data) {
+ void setLocaleData(byte[] data, int size) {
// Check if locale was set by the user:
Configuration conf = mContext.getResources().getConfiguration();
Locale loc = conf.locale;
@@ -157,9 +157,9 @@ public class SettingsHelper {
if (conf.userSetLocale) return; // Don't change if user set it in the SetupWizard
final String[] availableLocales = mContext.getAssets().getLocales();
- String localeCode = new String(data);
+ String localeCode = new String(data, 0, size);
String language = new String(data, 0, 2);
- String country = data.length > 4 ? new String(data, 3, 2) : "";
+ String country = size > 4 ? new String(data, 3, 2) : "";
loc = null;
for (int i = 0; i < availableLocales.length; i++) {
if (availableLocales[i].equals(localeCode)) {
diff --git a/packages/SharedStorageBackup/Android.mk b/packages/SharedStorageBackup/Android.mk
new file mode 100644
index 0000000..1d4f4da
--- /dev/null
+++ b/packages/SharedStorageBackup/Android.mk
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2011 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+
+LOCAL_PACKAGE_NAME := SharedStorageBackup
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
+########################
+include $(call all-makefiles-under,$(LOCAL_PATH))
+
diff --git a/packages/SharedStorageBackup/AndroidManifest.xml b/packages/SharedStorageBackup/AndroidManifest.xml
new file mode 100644
index 0000000..258059c
--- /dev/null
+++ b/packages/SharedStorageBackup/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+** Copyright 2011, 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.sharedstoragebackup" >
+
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
+
+ <application android:allowClearUserData="false"
+ android:permission="android.permission.CONFIRM_FULL_BACKUP"
+ android:fullBackupAgent=".SharedStorageAgent"
+ android:allowBackup="false" >
+ </application>
+</manifest>
diff --git a/packages/SharedStorageBackup/proguard.flags b/packages/SharedStorageBackup/proguard.flags
new file mode 100644
index 0000000..f43cb81
--- /dev/null
+++ b/packages/SharedStorageBackup/proguard.flags
@@ -0,0 +1 @@
+-keep class com.android.sharedstoragebackup.SharedStorageAgent
diff --git a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java
new file mode 100644
index 0000000..b02ca2e
--- /dev/null
+++ b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java
@@ -0,0 +1,93 @@
+package com.android.sharedstoragebackup;
+
+import android.app.backup.FullBackup;
+import android.app.backup.FullBackupAgent;
+import android.app.backup.BackupDataInput;
+import android.app.backup.BackupDataOutput;
+import android.content.Context;
+import android.os.Environment;
+import android.os.ParcelFileDescriptor;
+import android.os.storage.StorageManager;
+import android.os.storage.StorageVolume;
+import android.util.Slog;
+
+import java.io.File;
+import java.io.IOException;
+
+public class SharedStorageAgent extends FullBackupAgent {
+ static final String TAG = "SharedStorageAgent";
+ static final boolean DEBUG = true;
+
+ StorageVolume[] mVolumes;
+
+ @Override
+ public void onCreate() {
+ StorageManager mgr = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
+ if (mgr != null) {
+ mVolumes = mgr.getVolumeList();
+ } else {
+ Slog.e(TAG, "Unable to access Storage Manager");
+ }
+ }
+
+ @Override
+ public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+ ParcelFileDescriptor newState) throws IOException {
+ // If there are shared-storage volumes available, run the inherited directory-
+ // hierarchy backup process on them. By convention in the Storage Manager, the
+ // "primary" shared storage volume is first in the list.
+ if (mVolumes != null) {
+ for (int i = 0; i < mVolumes.length; i++) {
+ StorageVolume v = mVolumes[i];
+ // Express the contents of volume N this way in the tar stream:
+ // shared/N/path/to/file
+ // The restore will then extract to the given volume
+ String domain = FullBackup.SHARED_PREFIX + i;
+ processTree(null, domain, v.getPath(), null, data);
+ }
+ }
+ }
+
+ /**
+ * Incremental onRestore() implementation is not used.
+ */
+ @Override
+ public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
+ throws IOException {
+ }
+
+ /**
+ * Full restore of one file to shared storage
+ */
+ @Override
+ public void onRestoreFile(ParcelFileDescriptor data, long size,
+ int type, String domain, String relpath, long mode, long mtime)
+ throws IOException {
+ Slog.d(TAG, "Shared restore: [ " + domain + " : " + relpath + "]");
+
+ File outFile = null;
+
+ // The file path must be in the semantic form [number]/path/to/file...
+ int slash = relpath.indexOf('/');
+ if (slash > 0) {
+ try {
+ int i = Integer.parseInt(relpath.substring(0, slash));
+ if (i <= mVolumes.length) {
+ outFile = new File(mVolumes[i].getPath(), relpath.substring(slash + 1));
+ if (DEBUG) Slog.i(TAG, " => " + outFile.getAbsolutePath());
+ } else {
+ Slog.w(TAG, "Cannot restore data for unavailable volume " + i);
+ }
+ } catch (NumberFormatException e) {
+ if (DEBUG) Slog.w(TAG, "Bad volume number token: " + relpath.substring(0, slash));
+ }
+ } else {
+ if (DEBUG) Slog.i(TAG, "Can't find volume-number token");
+ }
+ if (outFile == null) {
+ Slog.e(TAG, "Skipping data with malformed path " + relpath);
+ }
+
+ FullBackup.restoreToFile(data, size, type, mode, mtime, outFile, false);
+ }
+}
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_default.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_default.png
new file mode 100644
index 0000000..e2584e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_pressed.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_pressed.png
new file mode 100644
index 0000000..58b8510
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_zoom_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_zoom_default.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_zoom_default.png
new file mode 100644
index 0000000..2795c34
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_zoom_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_zoom_pressed.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_zoom_pressed.png
new file mode 100644
index 0000000..bbed6a6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_zoom_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_zoom.xml b/packages/SystemUI/res/drawable/ic_sysbar_zoom.xml
new file mode 100644
index 0000000..977e002
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_sysbar_zoom.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true" android:drawable="@drawable/ic_sysbar_zoom_pressed" />
+ <item android:drawable="@drawable/ic_sysbar_zoom_default" />
+</selector>
+
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar.xml b/packages/SystemUI/res/layout-sw600dp/status_bar.xml
index d9f3f23..707a8cb 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar.xml
@@ -75,6 +75,13 @@
systemui:keyCode="82"
android:visibility="invisible"
/>
+ <com.android.systemui.statusbar.policy.CompatModeButton
+ android:id="@+id/compat_button"
+ android:layout_width="80dip"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_sysbar_zoom"
+ android:visibility="invisible"
+ />
</LinearLayout>
<!-- fake space bar zone -->
diff --git a/packages/SystemUI/res/values-fr-large/strings.xml b/packages/SystemUI/res/values-fr-large/strings.xml
index 447b174..f8dd55e 100644
--- a/packages/SystemUI/res/values-fr-large/strings.xml
+++ b/packages/SystemUI/res/values-fr-large/strings.xml
@@ -21,7 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="status_bar_clear_all_button" msgid="4661583896803349732">"Tout effacer"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="383145178755329067">"Aucune connexion"</string>
- <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="2535465294437586528">"Connecté au Wi-Fi."</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="2535465294437586528">"Connecté au Wi-Fi"</string>
<string name="gps_notification_searching_text" msgid="4467935186864208249">"Recherche de GPS en cours"</string>
<string name="gps_notification_found_text" msgid="6270628388918822956">"Position définie par GPS"</string>
<string name="notifications_off_title" msgid="1860117696034775851">"Notifications désactivées"</string>
diff --git a/packages/SystemUI/res/values-it-large/strings.xml b/packages/SystemUI/res/values-it-large/strings.xml
index 3cde529..18ccd07 100644
--- a/packages/SystemUI/res/values-it-large/strings.xml
+++ b/packages/SystemUI/res/values-it-large/strings.xml
@@ -19,8 +19,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Cancella tutto"</string>
- <string name="status_bar_settings_signal_meter_disconnected" msgid="383145178755329067">"Nessuna conness. Internet"</string>
+ <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Cancella"</string>
+ <string name="status_bar_settings_signal_meter_disconnected" msgid="383145178755329067">"Nessuna connessione"</string>
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="2535465294437586528">"Wi-Fi connesso"</string>
<string name="gps_notification_searching_text" msgid="4467935186864208249">"Ricerca del GPS"</string>
<string name="gps_notification_found_text" msgid="6270628388918822956">"Posizione stabilita dal GPS"</string>
diff --git a/packages/SystemUI/res/values-large/config.xml b/packages/SystemUI/res/values-large/config.xml
index 299ab97..4014f8d 100644
--- a/packages/SystemUI/res/values-large/config.xml
+++ b/packages/SystemUI/res/values-large/config.xml
@@ -20,14 +20,7 @@
<!-- These resources are around just to allow their values to be customized
for different hardware and product builds. -->
<resources>
- <integer name="config_status_bar_position">1</integer>
-
- <!-- Component to be used as the status bar service. Must implement the IStatusBar
- interface. This name is in the ComponentName flattened format (package/class) -->
- <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.tablet.TabletStatusBar</string>
-
<!-- Whether or not we show the number in the bar. -->
<bool name="config_statusBarShowNumber">false</bool>
-
</resources>
diff --git a/packages/SystemUI/res/values-ru-large/strings.xml b/packages/SystemUI/res/values-ru-large/strings.xml
index c48321e..bafb97f 100644
--- a/packages/SystemUI/res/values-ru-large/strings.xml
+++ b/packages/SystemUI/res/values-ru-large/strings.xml
@@ -19,11 +19,11 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Очистить"</string>
+ <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Очистить все"</string>
<string name="status_bar_settings_signal_meter_disconnected" msgid="383145178755329067">"Нет подключения к Интернету"</string>
- <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="2535465294437586528">"Wi-Fi: подключено"</string>
- <string name="gps_notification_searching_text" msgid="4467935186864208249">"Выполняется поиск при помощи GPS"</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="2535465294437586528">"Wi-Fi подключено"</string>
+ <string name="gps_notification_searching_text" msgid="4467935186864208249">"Поиск GPS"</string>
<string name="gps_notification_found_text" msgid="6270628388918822956">"Местоположение установлено с помощью GPS"</string>
- <string name="notifications_off_title" msgid="1860117696034775851">"Показ уведомлений отключен"</string>
- <string name="notifications_off_text" msgid="1439152806320786912">"Нажмите здесь, чтобы снова разрешить показ уведомлений."</string>
+ <string name="notifications_off_title" msgid="1860117696034775851">"Уведомления отключены"</string>
+ <string name="notifications_off_text" msgid="1439152806320786912">"Нажмите здесь, чтобы снова включить уведомления."</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp-port/config.xml b/packages/SystemUI/res/values-sw600dp-port/config.xml
new file mode 100644
index 0000000..ab7661a
--- /dev/null
+++ b/packages/SystemUI/res/values-sw600dp-port/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources>
+ <integer name="config_maxNotificationIcons">3</integer>
+</resources>
+
diff --git a/packages/SystemUI/res/values-sw600dp-port/dimens.xml b/packages/SystemUI/res/values-sw600dp-port/dimens.xml
index 78dd8c4..b8a6cfe 100644
--- a/packages/SystemUI/res/values-sw600dp-port/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-port/dimens.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- * Copyright (c) 2010, The Android Open Source Project
+ * Copyright (c) 2011, 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.
@@ -17,6 +17,6 @@
-->
<resources>
<!-- gap on either side of status bar notification icons -->
- <dimen name="status_bar_icon_padding">2dp</dimen>
+ <dimen name="status_bar_icon_padding">0dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
new file mode 100644
index 0000000..74b266d
--- /dev/null
+++ b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2011, 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.
+*/
+-->
+<resources>
+ <!-- gap on either side of status bar notification icons -->
+ <dimen name="status_bar_icon_padding">2dp</dimen>
+</resources>
+
diff --git a/packages/SystemUI/res/values-sw720dp/config.xml b/packages/SystemUI/res/values-sw720dp/config.xml
new file mode 100644
index 0000000..56b8e54
--- /dev/null
+++ b/packages/SystemUI/res/values-sw720dp/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+ for different hardware and product builds. -->
+<resources>
+ <integer name="config_maxNotificationIcons">5</integer>
+</resources>
+
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 954a871..7a4ac5d 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -25,16 +25,14 @@
data icon on devices -->
<bool name="config_hspa_data_distinguishable">false</bool>
- <!-- The location of the status bar.
- 0 - top
- 1 - bottom
- -->
- <integer name="config_status_bar_position">0</integer>
-
<!-- Component to be used as the status bar service. Must implement the IStatusBar
interface. This name is in the ComponentName flattened format (package/class) -->
<string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.PhoneStatusBar</string>
+ <!-- Component to be used as the system bar service. Must implement the IStatusBar
+ interface. This name is in the ComponentName flattened format (package/class) -->
+ <string name="config_systemBarComponent" translatable="false">com.android.systemui.statusbar.tablet.TabletStatusBar</string>
+
<!-- Whether or not we show the number in the bar. -->
<bool name="config_statusBarShowNumber">true</bool>
@@ -42,5 +40,8 @@
autodetected from the Configuration. -->
<bool name="config_showNavigationBar">false</bool>
+ <!-- How many icons may be shown at once in the system bar. Includes any
+ slots that may be reused for things like IME control. -->
+ <integer name="config_maxNotificationIcons">5</integer>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 870acd3..d7a5056 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -27,7 +27,10 @@ import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Binder;
import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.util.Slog;
+import android.view.IWindowManager;
public class SystemUIService extends Service {
static final String TAG = "SystemUIService";
@@ -36,7 +39,7 @@ public class SystemUIService extends Service {
* The class names of the stuff to start.
*/
final Object[] SERVICES = new Object[] {
- R.string.config_statusBarComponent,
+ 0, // system bar or status bar, filled in below.
com.android.systemui.power.PowerUI.class,
};
@@ -62,6 +65,17 @@ public class SystemUIService extends Service {
@Override
public void onCreate() {
+ // Pick status bar or system bar.
+ IWindowManager wm = IWindowManager.Stub.asInterface(
+ ServiceManager.getService(Context.WINDOW_SERVICE));
+ try {
+ SERVICES[0] = wm.canStatusBarHide()
+ ? R.string.config_statusBarComponent
+ : R.string.config_systemBarComponent;
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failing checking whether status bar can hide", e);
+ }
+
final int N = SERVICES.length;
mServices = new SystemUI[N];
for (int i=0; i<N; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
new file mode 100644
index 0000000..c3052e8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CompatModeButton.java
@@ -0,0 +1,64 @@
+/*
+ * 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.systemui.statusbar.policy;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.RemoteException;
+import android.util.AttributeSet;
+import android.util.Slog;
+import android.view.View;
+import android.widget.ImageView;
+
+import com.android.systemui.R;
+
+public class CompatModeButton extends ImageView implements View.OnClickListener {
+ private static final String TAG = "StatusBar.CompatModeButton";
+
+ private ActivityManager mAM;
+
+ public CompatModeButton(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public CompatModeButton(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs);
+
+ setClickable(true);
+
+ mAM = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+
+ setOnClickListener(this);
+
+ refresh();
+ }
+
+ @Override
+ public void onClick(View v) {
+ mAM.setFrontActivityScreenCompatMode(ActivityManager.COMPAT_MODE_TOGGLE);
+ }
+
+ public void refresh() {
+ int mode = mAM.getFrontActivityScreenCompatMode();
+ setVisibility((mode == ActivityManager.COMPAT_MODE_NEVER
+ || mode == ActivityManager.COMPAT_MODE_ALWAYS)
+ ? View.GONE
+ : View.VISIBLE
+ );
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 70a78df..3175a99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -446,12 +446,14 @@ public class NetworkController extends BroadcastReceiver {
}
boolean isCdmaEri() {
- final int iconIndex = mServiceState.getCdmaEriIconIndex();
- if (iconIndex != EriInfo.ROAMING_INDICATOR_OFF) {
- final int iconMode = mServiceState.getCdmaEriIconMode();
- if (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
- || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH) {
- return true;
+ if (mServiceState != null) {
+ final int iconIndex = mServiceState.getCdmaEriIconIndex();
+ if (iconIndex != EriInfo.ROAMING_INDICATOR_OFF) {
+ final int iconMode = mServiceState.getCdmaEriIconMode();
+ if (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
+ || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH) {
+ return true;
+ }
}
}
return false;
@@ -854,7 +856,7 @@ public class NetworkController extends BroadcastReceiver {
pw.print(" mDataActivity=");
pw.println(mDataActivity);
pw.print(" mServiceState=");
- pw.println(mServiceState.toString());
+ pw.println(mServiceState);
pw.print(" mNetworkName=");
pw.println(mNetworkName);
pw.print(" mNetworkNameDefault=");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
index e9db998..339e3f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
@@ -422,9 +422,8 @@ public class InputMethodsPanel extends LinearLayout implements StatusBarPanel,
Log.d(TAG, "Get text from: " + imi.getPackageName() + subtype.getNameResId()
+ imi.getServiceInfo().applicationInfo);
}
- // TODO: Change the language of subtype name according to subtype's locale.
- return mPackageManager.getText(
- imi.getPackageName(), subtype.getNameResId(), imi.getServiceInfo().applicationInfo);
+ return subtype.getDisplayName(
+ mContext, imi.getPackageName(), imi.getServiceInfo().applicationInfo);
}
private Drawable getSubtypeIcon(InputMethodInfo imi, InputMethodSubtype subtype) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 63bc9b7..ffb45ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -69,6 +69,7 @@ import com.android.systemui.R;
import com.android.systemui.statusbar.*;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
+import com.android.systemui.statusbar.policy.CompatModeButton;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.Prefs;
@@ -81,9 +82,6 @@ public class TabletStatusBar extends StatusBar implements
public static final boolean DEBUG = false;
public static final String TAG = "TabletStatusBar";
- public static final int MAX_NOTIFICATION_ICONS = 5;
- // IME switcher icon is big and occupy width of two icons
- public static final int MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE = MAX_NOTIFICATION_ICONS - 1;
public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
@@ -105,6 +103,7 @@ public class TabletStatusBar extends StatusBar implements
int mNaturalBarHeight = -1;
int mIconSize = -1;
int mIconHPadding = -1;
+ private int mMaxNotificationIcons = 5;
H mHandler = new H();
@@ -311,7 +310,7 @@ public class TabletStatusBar extends StatusBar implements
final Resources res = mContext.getResources();
final Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
return Math.max(res.getDimensionPixelSize(R.dimen.notification_panel_min_height),
- d.getHeight());
+ d.getRealHeight());
}
@Override
@@ -331,10 +330,10 @@ public class TabletStatusBar extends StatusBar implements
final Resources res = mContext.getResources();
mNaturalBarHeight = res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
+ com.android.internal.R.dimen.system_bar_height);
int newIconSize = res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_icon_size);
+ com.android.internal.R.dimen.system_bar_icon_size);
int newIconHPadding = res.getDimensionPixelSize(
R.dimen.status_bar_icon_padding);
@@ -344,6 +343,13 @@ public class TabletStatusBar extends StatusBar implements
mIconSize = newIconSize;
reloadAllNotificationIcons(); // reload the tray
}
+
+ final int numIcons = res.getInteger(R.integer.config_maxNotificationIcons);
+ if (numIcons != mMaxNotificationIcons) {
+ mMaxNotificationIcons = numIcons;
+ if (DEBUG) Slog.d(TAG, "max notification icons: " + mMaxNotificationIcons);
+ reloadAllNotificationIcons();
+ }
}
protected View makeStatusBarView() {
@@ -958,6 +964,10 @@ public class TabletStatusBar extends StatusBar implements
// See above re: lights-out policy for legacy apps.
if (visible) setLightsOn(true);
+
+ // XXX: HACK: not sure if this is the best way to catch a new activity that might require a
+ // change in compatibility features, but it's a start.
+ ((CompatModeButton) mBarContents.findViewById(R.id.compat_button)).refresh();
}
public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
@@ -1430,9 +1440,11 @@ public class TabletStatusBar extends StatusBar implements
// When IME button is visible, the number of notification icons should be decremented
// to fit the upper limit.
+ // IME switcher icon is big and occupy width of one icon
+ final int maxNotificationIconsImeButtonVisible = mMaxNotificationIcons - 1;
final int maxNotificationIconsCount =
(mInputMethodSwitchButton.getVisibility() != View.GONE) ?
- MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE : MAX_NOTIFICATION_ICONS;
+ maxNotificationIconsImeButtonVisible : mMaxNotificationIcons;
for (int i=0; i< maxNotificationIconsCount; i++) {
if (i>=N) break;
toShow.add(mNotificationData.get(N-i-1).icon);
diff --git a/packages/VpnDialogs/Android.mk b/packages/VpnDialogs/Android.mk
new file mode 100644
index 0000000..89f010a
--- /dev/null
+++ b/packages/VpnDialogs/Android.mk
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2011 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := VpnDialogs
+
+include $(BUILD_PACKAGE)
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
new file mode 100644
index 0000000..4e6784c
--- /dev/null
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.vpndialogs">
+
+ <application android:label="VpnDialogs">
+ <activity android:name=".ConfirmDialog"
+ android:theme="@style/transparent">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".ManageDialog"
+ android:theme="@style/transparent"
+ android:noHistory="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/packages/VpnDialogs/res/layout/confirm.xml b/packages/VpnDialogs/res/layout/confirm.xml
new file mode 100644
index 0000000..249b6e6
--- /dev/null
+++ b/packages/VpnDialogs/res/layout/confirm.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <ImageView android:id="@+id/icon"
+ android:layout_width="@android:dimen/app_icon_size"
+ android:layout_height="@android:dimen/app_icon_size"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:layout_marginRight="1mm"/>
+
+ <TextView android:id="@+id/warning"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentRight="true"
+ android:layout_below="@id/icon"
+ android:padding="2mm"
+ android:text="@string/warning"
+ android:textSize="18sp"/>
+
+ <TextView android:id="@+id/prompt"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true"
+ android:layout_toRightOf="@id/icon"
+ android:layout_above="@id/warning"
+ android:gravity="center_vertical"
+ android:textSize="20sp"/>
+
+ <CheckBox android:id="@+id/check"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentRight="true"
+ android:layout_below="@id/warning"
+ android:text="@string/accept"
+
+
+ android:textSize="18sp"
+ android:checked="false"/>
+
+</RelativeLayout>
diff --git a/packages/VpnDialogs/res/layout/manage.xml b/packages/VpnDialogs/res/layout/manage.xml
new file mode 100644
index 0000000..330b8e3
--- /dev/null
+++ b/packages/VpnDialogs/res/layout/manage.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:stretchColumns="0,1">
+
+ <TableRow>
+ <TextView android:text="@string/session" style="@style/label"/>
+ <TextView android:id="@+id/session" style="@style/value"/>
+ </TableRow>
+
+ <TableRow>
+ <TextView android:text="@string/duration" style="@style/label"/>
+ <TextView android:id="@+id/duration" style="@style/value"/>
+ </TableRow>
+
+ <TableRow>
+ <TextView android:text="@string/data_transmitted" style="@style/label"/>
+ <TextView android:id="@+id/data_transmitted" style="@style/value"/>
+ </TableRow>
+
+ <TableRow>
+ <TextView android:text="@string/data_received" style="@style/label"/>
+ <TextView android:id="@+id/data_received" style="@style/value"/>
+ </TableRow>
+
+</TableLayout>
diff --git a/packages/VpnDialogs/res/values/strings.xml b/packages/VpnDialogs/res/values/strings.xml
new file mode 100644
index 0000000..8186e26
--- /dev/null
+++ b/packages/VpnDialogs/res/values/strings.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <string name="prompt"><xliff:g id="app">%s</xliff:g>
+ attempts to create a VPN connection.
+ </string>
+
+ <string name="warning">By proceeding, you are giving the application
+ permission to intercept all network traffic.
+ <b>Do NOT accept unless you trust the application.</b> Otherwise,
+ you run the risk of having your data compromised by a malicious
+ software.
+ </string>
+
+ <string name="accept">I trust this application.</string>
+
+ <string name="configure">Configure</string>
+ <string name="disconnect">Disconnect</string>
+
+ <string name="session">Session:</string>
+ <string name="duration">Duration:</string>
+ <string name="data_transmitted">Data Transmitted:</string>
+ <string name="data_received">Data Received:</string>
+
+ <string name="blank_value">--</string>
+ <string name="data_value_format">
+ <xliff:g id="number">%1$s</xliff:g> bytes /
+ <xliff:g id="number">%2$s</xliff:g> packets
+ </string>
+</resources>
diff --git a/packages/VpnDialogs/res/values/styles.xml b/packages/VpnDialogs/res/values/styles.xml
new file mode 100644
index 0000000..6eae218
--- /dev/null
+++ b/packages/VpnDialogs/res/values/styles.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<resources>
+
+ <style name="transparent">
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowIsFloating">true</item>
+ </style>
+
+ <style name="label">
+ <item name="android:gravity">center_vertical|right</item>
+ <item name="android:paddingRight">5mm</item>
+ <item name="android:textSize">16sp</item>
+ </style>
+
+ <style name="value">
+ <item name="android:gravity">center_vertical|left</item>
+ <item name="android:textSize">18sp</item>
+ <item name="android:textStyle">bold</item>
+ <item name="android:text">@string/blank_value</item>
+ </style>
+</resources>
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
new file mode 100644
index 0000000..8fa6c7a
--- /dev/null
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ConfirmDialog.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2011 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.vpndialogs;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CompoundButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+public class ConfirmDialog extends Activity implements CompoundButton.OnCheckedChangeListener,
+ DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
+ private static final String TAG = "VpnConfirm";
+
+ private String mPackageName;
+
+ private ConnectivityManager mService;
+
+ private AlertDialog mDialog;
+ private Button mButton;
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ try {
+ mPackageName = getCallingPackage();
+ mService = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+
+ if (mPackageName.equals(mService.prepareVpn(null))) {
+ setResult(RESULT_OK);
+ finish();
+ return;
+ }
+
+ PackageManager pm = getPackageManager();
+ ApplicationInfo app = pm.getApplicationInfo(mPackageName, 0);
+
+ View view = View.inflate(this, R.layout.confirm, null);
+ ((ImageView) view.findViewById(R.id.icon)).setImageDrawable(app.loadIcon(pm));
+ ((TextView) view.findViewById(R.id.prompt)).setText(
+ getString(R.string.prompt, app.loadLabel(pm)));
+ ((CompoundButton) view.findViewById(R.id.check)).setOnCheckedChangeListener(this);
+
+ mDialog = new AlertDialog.Builder(this)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setTitle(android.R.string.dialog_alert_title)
+ .setView(view)
+ .setPositiveButton(android.R.string.ok, this)
+ .setNegativeButton(android.R.string.cancel, this)
+ .setCancelable(false)
+ .create();
+ mDialog.setOnDismissListener(this);
+ mDialog.show();
+
+ mButton = mDialog.getButton(DialogInterface.BUTTON_POSITIVE);
+ mButton.setEnabled(false);
+ } catch (Exception e) {
+ Log.e(TAG, "onResume", e);
+ finish();
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (mDialog != null) {
+ mDialog.setOnDismissListener(null);
+ mDialog.dismiss();
+ }
+ }
+
+ @Override
+ public void onCheckedChanged(CompoundButton button, boolean checked) {
+ mButton.setEnabled(checked);
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ try {
+ if (which == AlertDialog.BUTTON_POSITIVE &&
+ mPackageName.equals(mService.prepareVpn(mPackageName))) {
+ setResult(RESULT_OK);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "onClick", e);
+ }
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ finish();
+ }
+}
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
new file mode 100644
index 0000000..853e625
--- /dev/null
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2011 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.vpndialogs;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CompoundButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.io.DataInputStream;
+import java.io.FileInputStream;
+
+public class ManageDialog extends Activity implements
+ DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
+ private static final String TAG = "VpnManage";
+
+ private String mPackageName;
+ private String mInterfaceName;
+ private long mStartTime;
+
+ private ConnectivityManager mService;
+
+ private AlertDialog mDialog;
+ private TextView mDuration;
+ private TextView mDataTransmitted;
+ private TextView mDataReceived;
+
+ private Updater mUpdater;
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ try {
+ Intent intent = getIntent();
+ // TODO: Move constants into VpnBuilder.
+ mPackageName = intent.getStringExtra("packageName");
+ mInterfaceName = intent.getStringExtra("interfaceName");
+ mStartTime = intent.getLongExtra("startTime", 0);
+
+ mService = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+
+ PackageManager pm = getPackageManager();
+ ApplicationInfo app = pm.getApplicationInfo(mPackageName, 0);
+
+ View view = View.inflate(this, R.layout.manage, null);
+ String session = intent.getStringExtra("session");
+ if (session != null) {
+ ((TextView) view.findViewById(R.id.session)).setText(session);
+ }
+ mDuration = (TextView) view.findViewById(R.id.duration);
+ mDataTransmitted = (TextView) view.findViewById(R.id.data_transmitted);
+ mDataReceived = (TextView) view.findViewById(R.id.data_received);
+
+ mDialog = new AlertDialog.Builder(this)
+ .setIcon(app.loadIcon(pm))
+ .setTitle(app.loadLabel(pm))
+ .setView(view)
+ .setPositiveButton(R.string.configure, this)
+ .setNeutralButton(R.string.disconnect, this)
+ .setNegativeButton(android.R.string.cancel, this)
+ .create();
+ mDialog.setOnDismissListener(this);
+ mDialog.show();
+
+ mUpdater = new Updater();
+ mUpdater.sendEmptyMessage(0);
+ } catch (Exception e) {
+ Log.e(TAG, "onResume", e);
+ finish();
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (mDialog != null) {
+ mDialog.setOnDismissListener(null);
+ mDialog.dismiss();
+ }
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ try {
+ if (which == AlertDialog.BUTTON_POSITIVE) {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setPackage(mPackageName);
+ startActivity(intent);
+ } else if (which == AlertDialog.BUTTON_NEUTRAL) {
+ mService.prepareVpn(mPackageName);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "onClick", e);
+ }
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ finish();
+ }
+
+ private class Updater extends Handler {
+ public void handleMessage(Message message) {
+ removeMessages(0);
+
+ if (mDialog.isShowing()) {
+ if (mStartTime != 0) {
+ long seconds = (SystemClock.elapsedRealtime() - mStartTime) / 1000;
+ mDuration.setText(String.format("%02d:%02d:%02d",
+ seconds / 3600, seconds / 60 % 60, seconds % 60));
+ }
+
+ String[] numbers = getStatistics();
+ if (numbers != null) {
+ // [1] and [2] are received data in bytes and packets.
+ mDataReceived.setText(getString(R.string.data_value_format,
+ numbers[1], numbers[2]));
+
+ // [9] and [10] are transmitted data in bytes and packets.
+ mDataTransmitted.setText(getString(R.string.data_value_format,
+ numbers[9], numbers[10]));
+ }
+ sendEmptyMessageDelayed(0, 1000);
+ }
+ }
+ }
+
+ private String[] getStatistics() {
+ DataInputStream in = null;
+ try {
+ // See dev_seq_printf_stats() in net/core/dev.c.
+ in = new DataInputStream(new FileInputStream("/proc/net/dev"));
+ String prefix = mInterfaceName + ':';
+
+ while (true) {
+ String line = in.readLine().trim();
+ if (line.startsWith(prefix)) {
+ String[] numbers = line.substring(prefix.length()).split(" +");
+ if (numbers.length == 17) {
+ return numbers;
+ }
+ break;
+ }
+ }
+ } catch (Exception e) {
+ // ignore
+ } finally {
+ try {
+ in.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ return null;
+ }
+}